2015-11-05 06:32:32 +08:00
|
|
|
//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
|
2009-06-24 09:03:06 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-06-24 09:03:06 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-02-24 07:01:06 +08:00
|
|
|
#include "llvm/ADT/Optional.h"
|
2014-04-24 22:33:36 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2015-01-14 19:23:27 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2019-10-19 09:44:09 +08:00
|
|
|
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/MC/MCAsmBackend.h"
|
2009-08-31 16:08:38 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
2018-04-27 23:45:54 +08:00
|
|
|
#include "llvm/MC/MCAssembler.h"
|
2009-08-27 08:51:57 +08:00
|
|
|
#include "llvm/MC/MCCodeEmitter.h"
|
2016-08-27 01:58:37 +08:00
|
|
|
#include "llvm/MC/MCCodeView.h"
|
2009-06-24 09:03:06 +08:00
|
|
|
#include "llvm/MC/MCContext.h"
|
2009-08-31 16:08:38 +08:00
|
|
|
#include "llvm/MC/MCExpr.h"
|
2010-12-16 11:20:06 +08:00
|
|
|
#include "llvm/MC/MCFixupKindInfo.h"
|
2009-07-01 14:35:03 +08:00
|
|
|
#include "llvm/MC/MCInst.h"
|
2009-09-14 11:02:37 +08:00
|
|
|
#include "llvm/MC/MCInstPrinter.h"
|
2011-07-27 04:57:44 +08:00
|
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
2018-04-27 23:45:54 +08:00
|
|
|
#include "llvm/MC/MCObjectWriter.h"
|
2019-08-31 05:23:05 +08:00
|
|
|
#include "llvm/MC/MCRegister.h"
|
2011-07-19 04:57:22 +08:00
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
2009-08-11 02:15:01 +08:00
|
|
|
#include "llvm/MC/MCSectionMachO.h"
|
2016-04-18 17:17:29 +08:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2020-07-06 22:18:06 +08:00
|
|
|
#include "llvm/MC/MCSymbolXCOFF.h"
|
2009-07-12 04:10:48 +08:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-08-27 08:51:57 +08:00
|
|
|
#include "llvm/Support/Format.h"
|
2010-01-22 15:29:22 +08:00
|
|
|
#include "llvm/Support/FormattedStream.h"
|
2015-10-07 15:01:31 +08:00
|
|
|
#include "llvm/Support/LEB128.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2013-06-12 06:21:28 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2018-04-27 23:45:54 +08:00
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2010-12-20 04:43:38 +08:00
|
|
|
#include <cctype>
|
2015-11-05 06:32:32 +08:00
|
|
|
|
2009-06-24 09:03:06 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2015-04-09 21:04:20 +08:00
|
|
|
class MCAsmStreamer final : public MCStreamer {
|
2015-04-10 05:06:08 +08:00
|
|
|
std::unique_ptr<formatted_raw_ostream> OSOwner;
|
2010-01-22 15:29:22 +08:00
|
|
|
formatted_raw_ostream &OS;
|
2013-06-18 15:20:20 +08:00
|
|
|
const MCAsmInfo *MAI;
|
2014-03-06 13:51:42 +08:00
|
|
|
std::unique_ptr<MCInstPrinter> InstPrinter;
|
2018-04-27 23:45:54 +08:00
|
|
|
std::unique_ptr<MCAssembler> Assembler;
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2016-07-11 20:42:14 +08:00
|
|
|
SmallString<128> ExplicitCommentToEmit;
|
2010-01-22 15:29:22 +08:00
|
|
|
SmallString<128> CommentToEmit;
|
2010-01-23 03:17:48 +08:00
|
|
|
raw_svector_ostream CommentStream;
|
2018-04-27 23:45:54 +08:00
|
|
|
raw_null_ostream NullStream;
|
2010-02-04 02:18:30 +08:00
|
|
|
|
|
|
|
unsigned IsVerboseAsm : 1;
|
|
|
|
unsigned ShowInst : 1;
|
2011-10-18 07:05:28 +08:00
|
|
|
unsigned UseDwarfDirectory : 1;
|
2010-02-04 02:18:30 +08:00
|
|
|
|
2011-05-31 04:20:15 +08:00
|
|
|
void EmitRegisterName(int64_t Register);
|
2020-02-14 13:58:16 +08:00
|
|
|
void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
|
|
|
|
void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
|
2011-05-31 04:20:15 +08:00
|
|
|
|
2009-08-17 12:17:34 +08:00
|
|
|
public:
|
2015-04-10 05:06:08 +08:00
|
|
|
MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
|
2014-05-12 21:07:11 +08:00
|
|
|
bool isVerboseAsm, bool useDwarfDirectory,
|
2018-04-27 23:45:54 +08:00
|
|
|
MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
|
|
|
|
std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
|
2015-04-10 05:06:08 +08:00
|
|
|
: MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
|
2018-04-27 23:45:54 +08:00
|
|
|
MAI(Context.getAsmInfo()), InstPrinter(printer),
|
2019-08-15 23:54:37 +08:00
|
|
|
Assembler(std::make_unique<MCAssembler>(
|
2018-04-27 23:45:54 +08:00
|
|
|
Context, std::move(asmbackend), std::move(emitter),
|
|
|
|
(asmbackend) ? asmbackend->createObjectWriter(NullStream)
|
|
|
|
: nullptr)),
|
|
|
|
CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
|
|
|
|
ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
|
2015-05-27 20:13:06 +08:00
|
|
|
assert(InstPrinter);
|
|
|
|
if (IsVerboseAsm)
|
|
|
|
InstPrinter->setCommentStream(CommentStream);
|
2020-01-09 01:58:42 +08:00
|
|
|
if (Assembler->getBackendPtr())
|
|
|
|
setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
|
2020-02-25 10:09:27 +08:00
|
|
|
|
|
|
|
Context.setUseNamesOnTempLabels(true);
|
2010-02-10 08:10:18 +08:00
|
|
|
}
|
2009-06-24 09:03:06 +08:00
|
|
|
|
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant
expressions. This improves the handing of preprocessor expressions
that must be resolved at parse time. This idiom can be found as
assembling-time assertion checks in source-level assemblers. Note that
this relies on the MCStreamer to keep sufficient tabs on Section /
Fragment information which the MCAsmStreamer does not. As a result the
textual output may fail where the equivalent object generation would
pass. This can most easily be resolved by folding the MCAsmStreamer
and MCObjectStreamer together which is planned for in a separate
patch.
Currently, this feature is only enabled for assembly input, keeping IR
compilation consistent between assembly and object generation.
Reviewers: echristo, rnk, probinson, espindola, peter.smith
Reviewed By: peter.smith
Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D45164
llvm-svn: 331218
2018-05-01 03:22:40 +08:00
|
|
|
MCAssembler &getAssembler() { return *Assembler; }
|
|
|
|
MCAssembler *getAssemblerPtr() override { return nullptr; }
|
|
|
|
|
2010-01-22 15:29:22 +08:00
|
|
|
inline void EmitEOL() {
|
2016-07-11 20:42:14 +08:00
|
|
|
// Dump Explicit Comments here.
|
|
|
|
emitExplicitComments();
|
2010-01-23 03:17:48 +08:00
|
|
|
// If we don't have any comments, just emit a \n.
|
|
|
|
if (!IsVerboseAsm) {
|
2010-01-22 15:29:22 +08:00
|
|
|
OS << '\n';
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
EmitCommentsAndEOL();
|
|
|
|
}
|
2015-07-22 18:49:44 +08:00
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitSyntaxDirective() override;
|
2015-07-22 18:49:44 +08:00
|
|
|
|
2010-01-22 15:29:22 +08:00
|
|
|
void EmitCommentsAndEOL();
|
2010-02-03 07:37:42 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Return true if this streamer supports verbose assembly at all.
|
2014-03-08 15:02:02 +08:00
|
|
|
bool isVerboseAsm() const override { return IsVerboseAsm; }
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Do we support EmitRawText?
|
2014-03-08 15:02:02 +08:00
|
|
|
bool hasRawTextSupport() const override { return true; }
|
2010-02-10 07:00:14 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Add a comment that can be emitted to the generated .s file to make the
|
|
|
|
/// output of the compiler more readable. This only affects the MCAsmStreamer
|
|
|
|
/// and only when verbose assembly output is enabled.
|
2016-12-28 18:12:48 +08:00
|
|
|
void AddComment(const Twine &T, bool EOL = true) override;
|
2010-02-10 07:00:14 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Add a comment showing the encoding of an instruction.
|
2019-02-04 20:51:26 +08:00
|
|
|
void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
|
2010-02-10 07:00:14 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Return a raw_ostream that comments can be written to.
|
2010-01-23 03:17:48 +08:00
|
|
|
/// Unlike AddComment, you are required to terminate comments with \n if you
|
|
|
|
/// use this method.
|
2014-03-08 15:02:02 +08:00
|
|
|
raw_ostream &GetCommentOS() override {
|
2010-01-23 03:17:48 +08:00
|
|
|
if (!IsVerboseAsm)
|
|
|
|
return nulls(); // Discard comments unless in verbose asm mode.
|
|
|
|
return CommentStream;
|
|
|
|
}
|
2010-02-10 07:00:14 +08:00
|
|
|
|
2014-03-02 17:09:27 +08:00
|
|
|
void emitRawComment(const Twine &T, bool TabPrefix = true) override;
|
2014-01-17 00:28:37 +08:00
|
|
|
|
2016-07-11 20:42:14 +08:00
|
|
|
void addExplicitComment(const Twine &T) override;
|
2016-10-11 06:49:37 +08:00
|
|
|
void emitExplicitComments() override;
|
2016-07-11 20:42:14 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Emit a blank line to a .s file to pretty it up.
|
2014-03-08 15:02:02 +08:00
|
|
|
void AddBlankLine() override {
|
2010-01-23 03:52:01 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
2010-02-10 07:00:14 +08:00
|
|
|
|
2009-08-17 12:17:34 +08:00
|
|
|
/// @name MCStreamer Interface
|
|
|
|
/// @{
|
2009-06-24 09:03:06 +08:00
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void changeSection(MCSection *Section, const MCExpr *Subsection) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2018-03-10 02:42:25 +08:00
|
|
|
void emitELFSymverDirective(StringRef AliasName,
|
2018-03-09 11:13:37 +08:00
|
|
|
const MCSymbol *Aliasee) override;
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
|
2020-11-17 19:53:01 +08:00
|
|
|
|
|
|
|
StringRef getMnemonic(MCInst &MI) override {
|
|
|
|
return InstPrinter->getMnemonic(&MI).first;
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitAssemblerFlag(MCAssemblerFlag Flag) override;
|
|
|
|
void emitLinkerOptions(ArrayRef<std::string> Options) override;
|
|
|
|
void emitDataRegion(MCDataRegionType Kind) override;
|
|
|
|
void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
|
2018-12-14 09:14:10 +08:00
|
|
|
unsigned Update, VersionTuple SDKVersion) override;
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
|
2018-12-14 09:14:10 +08:00
|
|
|
unsigned Update, VersionTuple SDKVersion) override;
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitThumbFunc(MCSymbol *Func) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
|
|
|
|
void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
|
2020-11-03 04:32:06 +08:00
|
|
|
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
|
|
|
|
void EmitCOFFSymbolStorageClass(int StorageClass) override;
|
|
|
|
void EmitCOFFSymbolType(int Type) override;
|
|
|
|
void EndCOFFSymbolDef() override;
|
2015-05-30 12:56:02 +08:00
|
|
|
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
|
2018-01-10 07:49:30 +08:00
|
|
|
void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
|
2017-01-02 11:00:19 +08:00
|
|
|
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
|
2018-07-27 04:11:26 +08:00
|
|
|
void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
|
[XCOFF][AIX] Differentiate usage of label symbol and csect symbol
Summary:
We are using symbols to represent label and csect interchangeably before, and that could be a problem.
There are cases we would need to add storage mapping class to the symbol if that symbol is actually the name of a csect, but it's hard for us to figure out whether that symbol is a label or csect.
This patch intend to do the following:
1. Construct a QualName (A name include the storage mapping class)
MCSymbolXCOFF for every MCSectionXCOFF.
2. Keep a pointer to that QualName inside of MCSectionXCOFF.
3. Use that QualName whenever we need a symbol refers to that
MCSectionXCOFF.
4. Adapt the snowball effect from the above changes in
XCOFFObjectWriter.cpp.
Reviewers: xingxue, DiggerLin, sfertile, daltenty, hubert.reinterpretcast
Reviewed By: DiggerLin, daltenty
Subscribers: wuzish, nemanjai, mgorny, hiraditya, kbarton, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69633
2019-11-08 22:26:28 +08:00
|
|
|
MCSymbol *CsectSym,
|
Enable assembly output of local commons for AIX
Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
llvm-svn: 368306
2019-08-08 23:40:35 +08:00
|
|
|
unsigned ByteAlign) override;
|
[AIX] supporting the visibility attribute for aix assembly
SUMMARY:
in the aix assembly , it do not have .hidden and .protected directive.
in current llvm. if a function or a variable which has visibility attribute, it will generate something like the .hidden or .protected , it can not recognize by aix as.
in aix assembly, the visibility attribute are support in the pseudo-op like
.extern Name [ , Visibility ]
.globl Name [, Visibility ]
.weak Name [, Visibility ]
in this patch, we implement the visibility attribute for the global variable, function or extern function .
for example.
extern __attribute__ ((visibility ("hidden"))) int
bar(int* ip);
__attribute__ ((visibility ("hidden"))) int b = 0;
__attribute__ ((visibility ("hidden"))) int
foo(int* ip){
return (*ip)++;
}
the visibility of .comm linkage do not support , we will have a separate patch for it.
we have the unsupported cases ("default" and "internal") , we will implement them in a a separate patch for it.
Reviewers: Jason Liu ,hubert.reinterpretcast,James Henderson
Differential Revision: https://reviews.llvm.org/D75866
2020-06-10 04:15:06 +08:00
|
|
|
void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
|
|
|
|
MCSymbolAttr Linakge,
|
|
|
|
MCSymbolAttr Visibility) override;
|
2020-07-06 22:18:06 +08:00
|
|
|
void emitXCOFFRenameDirective(const MCSymbol *Name,
|
|
|
|
StringRef Rename) override;
|
[AIX] supporting the visibility attribute for aix assembly
SUMMARY:
in the aix assembly , it do not have .hidden and .protected directive.
in current llvm. if a function or a variable which has visibility attribute, it will generate something like the .hidden or .protected , it can not recognize by aix as.
in aix assembly, the visibility attribute are support in the pseudo-op like
.extern Name [ , Visibility ]
.globl Name [, Visibility ]
.weak Name [, Visibility ]
in this patch, we implement the visibility attribute for the global variable, function or extern function .
for example.
extern __attribute__ ((visibility ("hidden"))) int
bar(int* ip);
__attribute__ ((visibility ("hidden"))) int b = 0;
__attribute__ ((visibility ("hidden"))) int
foo(int* ip){
return (*ip)++;
}
the visibility of .comm linkage do not support , we will have a separate patch for it.
we have the unsupported cases ("default" and "internal") , we will implement them in a a separate patch for it.
Reviewers: Jason Liu ,hubert.reinterpretcast,James Henderson
Differential Revision: https://reviews.llvm.org/D75866
2020-06-10 04:15:06 +08:00
|
|
|
|
2016-12-02 07:39:08 +08:00
|
|
|
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
2014-03-08 15:02:02 +08:00
|
|
|
unsigned ByteAlignment) override;
|
2009-07-15 02:17:10 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// Emit a local common (.lcomm) symbol.
|
2010-01-23 15:47:02 +08:00
|
|
|
///
|
|
|
|
/// @param Symbol - The common symbol to emit.
|
|
|
|
/// @param Size - The size of the common symbol.
|
2012-08-24 00:54:08 +08:00
|
|
|
/// @param ByteAlignment - The alignment of the common symbol in bytes.
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
2014-03-08 15:02:02 +08:00
|
|
|
unsigned ByteAlignment) override;
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
|
2018-07-03 01:29:43 +08:00
|
|
|
uint64_t Size = 0, unsigned ByteAlignment = 0,
|
|
|
|
SMLoc Loc = SMLoc()) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
|
2015-05-22 03:20:38 +08:00
|
|
|
unsigned ByteAlignment = 0) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitBinaryData(StringRef Data) override;
|
[codeview] Improve readability of type record assembly
Adds the method MCStreamer::EmitBinaryData, which is usually an alias
for EmitBytes. In the MCAsmStreamer case, it is overridden to emit hex
dump output like this:
.byte 0x0e, 0x00, 0x08, 0x10
.byte 0x03, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x10, 0x00, 0x00
Also, when verbose asm comments are enabled, this patch prints the dump
output for each comment before its record, like this:
# ArgList (0x1000) {
# TypeLeafKind: LF_ARGLIST (0x1201)
# NumArgs: 0
# Arguments [
# ]
# }
.byte 0x06, 0x00, 0x01, 0x12
.byte 0x00, 0x00, 0x00, 0x00
This should make debugging easier and testing more convenient.
Reviewers: aaboud
Subscribers: majnemer, zturner, amccarth, aaboud, llvm-commits
Differential Revision: http://reviews.llvm.org/D20711
llvm-svn: 271313
2016-06-01 02:45:36 +08:00
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void emitBytes(StringRef Data) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitValueImpl(const MCExpr *Value, unsigned Size,
|
2015-09-21 07:35:59 +08:00
|
|
|
SMLoc Loc = SMLoc()) override;
|
2020-02-15 14:40:47 +08:00
|
|
|
void emitIntValue(uint64_t Value, unsigned Size) override;
|
|
|
|
void emitIntValueInHex(uint64_t Value, unsigned Size) override;
|
|
|
|
void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-14 05:26:21 +08:00
|
|
|
void emitULEB128Value(const MCExpr *Value) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-14 05:26:21 +08:00
|
|
|
void emitSLEB128Value(const MCExpr *Value) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitDTPRel32Value(const MCExpr *Value) override;
|
|
|
|
void emitDTPRel64Value(const MCExpr *Value) override;
|
|
|
|
void emitTPRel32Value(const MCExpr *Value) override;
|
|
|
|
void emitTPRel64Value(const MCExpr *Value) override;
|
2016-08-23 00:18:42 +08:00
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitGPRel64Value(const MCExpr *Value) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitGPRel32Value(const MCExpr *Value) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2016-05-28 13:57:48 +08:00
|
|
|
void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
|
|
|
|
SMLoc Loc = SMLoc()) override;
|
|
|
|
|
|
|
|
void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
|
|
|
|
SMLoc Loc = SMLoc()) override;
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
|
2014-03-08 15:02:02 +08:00
|
|
|
unsigned ValueSize = 1,
|
|
|
|
unsigned MaxBytesToEmit = 0) override;
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void emitCodeAlignment(unsigned ByteAlignment,
|
2014-03-08 15:02:02 +08:00
|
|
|
unsigned MaxBytesToEmit = 0) override;
|
|
|
|
|
2015-11-05 07:59:18 +08:00
|
|
|
void emitValueToOffset(const MCExpr *Offset,
|
2016-12-14 18:43:58 +08:00
|
|
|
unsigned char Value,
|
|
|
|
SMLoc Loc) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitFileDirective(StringRef Filename) override;
|
2018-02-23 05:03:33 +08:00
|
|
|
Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
|
|
|
|
StringRef Directory,
|
|
|
|
StringRef Filename,
|
2019-04-05 07:34:38 +08:00
|
|
|
Optional<MD5::MD5Result> Checksum = None,
|
2018-02-24 07:01:06 +08:00
|
|
|
Optional<StringRef> Source = None,
|
2018-02-23 05:03:33 +08:00
|
|
|
unsigned CUID = 0) override;
|
2018-03-30 01:16:41 +08:00
|
|
|
void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
|
2019-04-05 07:34:38 +08:00
|
|
|
Optional<MD5::MD5Result> Checksum,
|
2018-03-30 01:16:41 +08:00
|
|
|
Optional<StringRef> Source,
|
|
|
|
unsigned CUID = 0) override;
|
2020-02-14 05:26:21 +08:00
|
|
|
void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
|
|
|
|
unsigned Flags, unsigned Isa,
|
|
|
|
unsigned Discriminator,
|
2014-03-08 15:02:02 +08:00
|
|
|
StringRef FileName) override;
|
2014-04-01 16:07:52 +08:00
|
|
|
MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2017-09-20 02:14:45 +08:00
|
|
|
bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
|
|
|
|
ArrayRef<uint8_t> Checksum,
|
|
|
|
unsigned ChecksumKind) override;
|
2016-09-08 00:15:31 +08:00
|
|
|
bool EmitCVFuncIdDirective(unsigned FuncId) override;
|
|
|
|
bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
|
|
|
|
unsigned IAFile, unsigned IALine,
|
|
|
|
unsigned IACol, SMLoc Loc) override;
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
|
2016-01-29 08:49:42 +08:00
|
|
|
unsigned Column, bool PrologueEnd, bool IsStmt,
|
2016-09-08 00:15:31 +08:00
|
|
|
StringRef FileName, SMLoc Loc) override;
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
|
2016-01-29 08:49:42 +08:00
|
|
|
const MCSymbol *FnEnd) override;
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
|
2016-09-08 00:15:31 +08:00
|
|
|
unsigned SourceFileId,
|
|
|
|
unsigned SourceLineNum,
|
|
|
|
const MCSymbol *FnStartSym,
|
|
|
|
const MCSymbol *FnEndSym) override;
|
2019-08-05 22:16:58 +08:00
|
|
|
|
|
|
|
void PrintCVDefRangePrefix(
|
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeRegisterRelHeader DRHdr) override;
|
2019-08-05 22:16:58 +08:00
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVDefRangeDirective(
|
2016-02-05 09:55:49 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
|
2019-08-05 22:16:58 +08:00
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeRegisterHeader DRHdr) override;
|
2019-08-05 22:16:58 +08:00
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeFramePointerRelHeader DRHdr) override;
|
2019-08-05 22:16:58 +08:00
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void emitCVStringTableDirective() override;
|
|
|
|
void emitCVFileChecksumsDirective() override;
|
|
|
|
void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
|
[codeview] Implement FPO data assembler directives
Summary:
This adds a set of new directives that describe 32-bit x86 prologues.
The directives are limited and do not expose the full complexity of
codeview FPO data. They are merely a convenience for the compiler to
generate more readable assembly so we don't need to generate tons of
labels in CodeGen. If our prologue emission changes in the future, we
can change the set of available directives to suit our needs. These are
modelled after the .seh_ directives, which use a different format that
interacts with exception handling.
The directives are:
.cv_fpo_proc _foo
.cv_fpo_pushreg ebp/ebx/etc
.cv_fpo_setframe ebp/esi/etc
.cv_fpo_stackalloc 200
.cv_fpo_endprologue
.cv_fpo_endproc
.cv_fpo_data _foo
I tried to follow the implementation of ARM EHABI CFI directives by
sinking most directives out of MCStreamer and into X86TargetStreamer.
This helps avoid polluting non-X86 code with WinCOFF specific logic.
I used cdb to confirm that this can show locals in parent CSRs in a few
cases, most importantly the one where we use ESI as a frame pointer,
i.e. the one in http://crbug.com/756153#c28
Once we have cdb integration in debuginfo-tests, we can add integration
tests there.
Reviewers: majnemer, hans
Subscribers: aemerson, mgorny, kristof.beyls, llvm-commits, hiraditya
Differential Revision: https://reviews.llvm.org/D38776
llvm-svn: 315513
2017-10-12 05:24:33 +08:00
|
|
|
void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
|
2016-01-29 08:49:42 +08:00
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitIdent(StringRef IdentString) override;
|
2020-02-14 13:58:16 +08:00
|
|
|
void emitCFIBKeyFrame() override;
|
|
|
|
void emitCFISections(bool EH, bool Debug) override;
|
|
|
|
void emitCFIDefCfa(int64_t Register, int64_t Offset) override;
|
|
|
|
void emitCFIDefCfaOffset(int64_t Offset) override;
|
|
|
|
void emitCFIDefCfaRegister(int64_t Register) override;
|
|
|
|
void emitCFIOffset(int64_t Register, int64_t Offset) override;
|
|
|
|
void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
|
|
|
|
void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
|
|
|
|
void emitCFIRememberState() override;
|
|
|
|
void emitCFIRestoreState() override;
|
|
|
|
void emitCFIRestore(int64_t Register) override;
|
|
|
|
void emitCFISameValue(int64_t Register) override;
|
|
|
|
void emitCFIRelOffset(int64_t Register, int64_t Offset) override;
|
|
|
|
void emitCFIAdjustCfaOffset(int64_t Adjustment) override;
|
|
|
|
void emitCFIEscape(StringRef Values) override;
|
|
|
|
void emitCFIGnuArgsSize(int64_t Size) override;
|
|
|
|
void emitCFISignalFrame() override;
|
|
|
|
void emitCFIUndefined(int64_t Register) override;
|
|
|
|
void emitCFIRegister(int64_t Register1, int64_t Register2) override;
|
|
|
|
void emitCFIWindowSave() override;
|
|
|
|
void emitCFINegateRAState() override;
|
|
|
|
void emitCFIReturnColumn(int64_t Register) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
|
|
|
|
void EmitWinCFIEndProc(SMLoc Loc) override;
|
2018-10-27 14:13:06 +08:00
|
|
|
void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
|
2017-10-10 09:26:25 +08:00
|
|
|
void EmitWinCFIStartChained(SMLoc Loc) override;
|
|
|
|
void EmitWinCFIEndChained(SMLoc Loc) override;
|
2019-08-31 05:23:05 +08:00
|
|
|
void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
|
|
|
|
void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
|
2017-10-10 09:26:25 +08:00
|
|
|
SMLoc Loc) override;
|
|
|
|
void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
|
2019-08-31 05:23:05 +08:00
|
|
|
void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
|
2017-10-10 09:26:25 +08:00
|
|
|
SMLoc Loc) override;
|
2019-08-31 05:23:05 +08:00
|
|
|
void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
|
2017-10-10 09:26:25 +08:00
|
|
|
SMLoc Loc) override;
|
|
|
|
void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
|
|
|
|
void EmitWinCFIEndProlog(SMLoc Loc) override;
|
|
|
|
|
|
|
|
void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
|
|
|
|
SMLoc Loc) override;
|
|
|
|
void EmitWinEHHandlerData(SMLoc Loc) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
[MC] Add assembler support for .cg_profile.
Object FIle Representation
At codegen time this is emitted into the ELF file a pair of symbol indices and a weight. In assembly it looks like:
.cg_profile a, b, 32
.cg_profile freq, a, 11
.cg_profile freq, b, 20
When writing an ELF file these are put into a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight).
Differential Revision: https://reviews.llvm.org/D44965
llvm-svn: 333823
2018-06-03 00:33:01 +08:00
|
|
|
void emitCGProfileEntry(const MCSymbolRefExpr *From,
|
|
|
|
const MCSymbolRefExpr *To, uint64_t Count) override;
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
|
2014-03-08 15:02:02 +08:00
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitBundleAlignMode(unsigned AlignPow2) override;
|
|
|
|
void emitBundleLock(bool AlignToEnd) override;
|
|
|
|
void emitBundleUnlock() override;
|
2012-12-21 03:05:53 +08:00
|
|
|
|
2020-07-15 04:44:00 +08:00
|
|
|
Optional<std::pair<bool, std::string>>
|
|
|
|
emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
|
|
|
|
SMLoc Loc, const MCSubtargetInfo &STI) override;
|
2015-11-12 21:33:00 +08:00
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitAddrsig() override;
|
|
|
|
void emitAddrsigSym(const MCSymbol *Sym) override;
|
2018-07-18 06:17:18 +08:00
|
|
|
|
2018-03-14 01:50:27 +08:00
|
|
|
/// If this file is backed by an assembly streamer, this dumps the specified
|
|
|
|
/// string in the output .s file. This capability is indicated by the
|
|
|
|
/// hasRawTextSupport() predicate.
|
2020-02-16 00:52:56 +08:00
|
|
|
void emitRawTextImpl(StringRef String) override;
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void finishImpl() override;
|
2009-08-17 12:17:34 +08:00
|
|
|
};
|
2009-06-25 03:25:34 +08:00
|
|
|
|
2009-08-17 12:17:34 +08:00
|
|
|
} // end anonymous namespace.
|
2009-06-24 09:03:06 +08:00
|
|
|
|
2016-12-28 18:12:48 +08:00
|
|
|
void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
|
2010-01-22 15:29:22 +08:00
|
|
|
if (!IsVerboseAsm) return;
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-22 15:29:22 +08:00
|
|
|
T.toVector(CommentToEmit);
|
2018-07-31 03:41:25 +08:00
|
|
|
|
2016-12-28 18:12:48 +08:00
|
|
|
if (EOL)
|
|
|
|
CommentToEmit.push_back('\n'); // Place comment in a new line.
|
2010-01-22 15:29:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmStreamer::EmitCommentsAndEOL() {
|
2010-01-23 03:17:48 +08:00
|
|
|
if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
|
|
|
|
OS << '\n';
|
|
|
|
return;
|
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2015-03-18 18:17:07 +08:00
|
|
|
StringRef Comments = CommentToEmit;
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-23 03:17:48 +08:00
|
|
|
assert(Comments.back() == '\n' &&
|
|
|
|
"Comment array not newline terminated");
|
|
|
|
do {
|
2010-01-22 15:29:22 +08:00
|
|
|
// Emit a line of comments.
|
2013-06-18 15:20:20 +08:00
|
|
|
OS.PadToColumn(MAI->getCommentColumn());
|
2010-01-22 15:29:22 +08:00
|
|
|
size_t Position = Comments.find('\n');
|
2013-06-18 15:20:20 +08:00
|
|
|
OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-22 15:29:22 +08:00
|
|
|
Comments = Comments.substr(Position+1);
|
2010-01-23 03:17:48 +08:00
|
|
|
} while (!Comments.empty());
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-23 05:16:10 +08:00
|
|
|
CommentToEmit.clear();
|
2010-01-22 15:29:22 +08:00
|
|
|
}
|
|
|
|
|
2009-06-26 05:03:18 +08:00
|
|
|
static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
|
2016-06-04 12:02:18 +08:00
|
|
|
assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
|
2009-06-26 05:03:18 +08:00
|
|
|
return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
|
|
|
|
}
|
|
|
|
|
2014-01-17 00:28:37 +08:00
|
|
|
void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
|
|
|
|
if (TabPrefix)
|
|
|
|
OS << '\t';
|
|
|
|
OS << MAI->getCommentString() << T;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2016-07-11 20:42:14 +08:00
|
|
|
void MCAsmStreamer::addExplicitComment(const Twine &T) {
|
|
|
|
StringRef c = T.getSingleStringRef();
|
|
|
|
if (c.equals(StringRef(MAI->getSeparatorString())))
|
|
|
|
return;
|
|
|
|
if (c.startswith(StringRef("//"))) {
|
|
|
|
ExplicitCommentToEmit.append("\t");
|
|
|
|
ExplicitCommentToEmit.append(MAI->getCommentString());
|
|
|
|
// drop //
|
|
|
|
ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
|
|
|
|
} else if (c.startswith(StringRef("/*"))) {
|
|
|
|
size_t p = 2, len = c.size() - 2;
|
|
|
|
// emit each line in comment as separate newline.
|
|
|
|
do {
|
|
|
|
size_t newp = std::min(len, c.find_first_of("\r\n", p));
|
|
|
|
ExplicitCommentToEmit.append("\t");
|
|
|
|
ExplicitCommentToEmit.append(MAI->getCommentString());
|
|
|
|
ExplicitCommentToEmit.append(c.slice(p, newp).str());
|
|
|
|
// If we have another line in this comment add line
|
|
|
|
if (newp < len)
|
|
|
|
ExplicitCommentToEmit.append("\n");
|
|
|
|
p = newp + 1;
|
|
|
|
} while (p < len);
|
|
|
|
} else if (c.startswith(StringRef(MAI->getCommentString()))) {
|
|
|
|
ExplicitCommentToEmit.append("\t");
|
|
|
|
ExplicitCommentToEmit.append(c.str());
|
|
|
|
} else if (c.front() == '#') {
|
2016-07-29 22:42:00 +08:00
|
|
|
|
|
|
|
ExplicitCommentToEmit.append("\t");
|
|
|
|
ExplicitCommentToEmit.append(MAI->getCommentString());
|
|
|
|
ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
|
2016-07-11 20:42:14 +08:00
|
|
|
} else
|
|
|
|
assert(false && "Unexpected Assembly Comment");
|
|
|
|
// full line comments immediately output
|
|
|
|
if (c.back() == '\n')
|
|
|
|
emitExplicitComments();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmStreamer::emitExplicitComments() {
|
|
|
|
StringRef Comments = ExplicitCommentToEmit;
|
|
|
|
if (!Comments.empty())
|
|
|
|
OS << Comments;
|
|
|
|
ExplicitCommentToEmit.clear();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::changeSection(MCSection *Section,
|
2013-04-18 05:18:16 +08:00
|
|
|
const MCExpr *Subsection) {
|
2009-08-19 13:49:37 +08:00
|
|
|
assert(Section && "Cannot switch to a null section!");
|
2017-12-20 22:55:10 +08:00
|
|
|
if (MCTargetStreamer *TS = getTargetStreamer()) {
|
|
|
|
TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
|
|
|
|
} else {
|
|
|
|
Section->PrintSwitchToSection(
|
|
|
|
*MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
|
|
|
|
Subsection);
|
|
|
|
}
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2018-03-10 02:42:25 +08:00
|
|
|
void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
|
2018-03-09 11:13:37 +08:00
|
|
|
const MCSymbol *Aliasee) {
|
|
|
|
OS << ".symver ";
|
|
|
|
Aliasee->print(OS, MAI);
|
2018-03-10 02:42:25 +08:00
|
|
|
OS << ", " << AliasName;
|
2018-03-09 11:13:37 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
|
|
|
|
MCStreamer::emitLabel(Symbol, Loc);
|
2009-06-25 01:00:42 +08:00
|
|
|
|
2015-06-09 08:31:39 +08:00
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << MAI->getLabelSuffix();
|
|
|
|
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
|
2014-03-29 15:34:53 +08:00
|
|
|
StringRef str = MCLOHIdToName(Kind);
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
int NbArgs = MCLOHIdToNbArgs(Kind);
|
|
|
|
assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
|
|
|
|
assert(str != "" && "Invalid LOH name");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
|
|
|
|
bool IsFirst = true;
|
2016-06-26 22:49:00 +08:00
|
|
|
for (const MCSymbol *Arg : Args) {
|
2014-03-29 15:34:53 +08:00
|
|
|
if (!IsFirst)
|
|
|
|
OS << ", ";
|
|
|
|
IsFirst = false;
|
2016-06-26 22:49:00 +08:00
|
|
|
Arg->print(OS, MAI);
|
2014-03-29 15:34:53 +08:00
|
|
|
}
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
|
2009-07-17 01:56:39 +08:00
|
|
|
switch (Flag) {
|
2010-09-30 10:45:56 +08:00
|
|
|
case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;
|
2010-01-23 14:39:22 +08:00
|
|
|
case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
|
2013-06-18 15:20:20 +08:00
|
|
|
case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;
|
|
|
|
case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;
|
|
|
|
case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;
|
2009-07-17 01:56:39 +08:00
|
|
|
}
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-07-14 05:03:15 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
|
2013-01-18 09:25:48 +08:00
|
|
|
assert(!Options.empty() && "At least one option is required!");
|
|
|
|
OS << "\t.linker_option \"" << Options[0] << '"';
|
|
|
|
for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
|
|
|
|
ie = Options.end(); it != ie; ++it) {
|
|
|
|
OS << ", " << '"' << *it << '"';
|
|
|
|
}
|
2016-07-18 23:24:03 +08:00
|
|
|
EmitEOL();
|
2013-01-18 09:25:48 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
|
2013-06-18 15:20:20 +08:00
|
|
|
if (!MAI->doesSupportDataRegionDirectives())
|
2012-05-19 03:12:01 +08:00
|
|
|
return;
|
|
|
|
switch (Kind) {
|
|
|
|
case MCDR_DataRegion: OS << "\t.data_region"; break;
|
|
|
|
case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
|
|
|
|
case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
|
|
|
|
case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
|
|
|
|
case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
|
|
|
|
}
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-12-14 08:12:46 +08:00
|
|
|
static const char *getVersionMinDirective(MCVersionMinType Type) {
|
|
|
|
switch (Type) {
|
|
|
|
case MCVM_WatchOSVersionMin: return ".watchos_version_min";
|
|
|
|
case MCVM_TvOSVersionMin: return ".tvos_version_min";
|
|
|
|
case MCVM_IOSVersionMin: return ".ios_version_min";
|
|
|
|
case MCVM_OSXVersionMin: return ".macosx_version_min";
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid MC version min type");
|
|
|
|
}
|
|
|
|
|
2018-12-14 09:14:10 +08:00
|
|
|
static void EmitSDKVersionSuffix(raw_ostream &OS,
|
|
|
|
const VersionTuple &SDKVersion) {
|
|
|
|
if (SDKVersion.empty())
|
|
|
|
return;
|
|
|
|
OS << '\t' << "sdk_version " << SDKVersion.getMajor();
|
|
|
|
if (auto Minor = SDKVersion.getMinor()) {
|
|
|
|
OS << ", " << *Minor;
|
|
|
|
if (auto Subminor = SDKVersion.getSubminor()) {
|
|
|
|
OS << ", " << *Subminor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
|
2018-12-14 09:14:10 +08:00
|
|
|
unsigned Minor, unsigned Update,
|
|
|
|
VersionTuple SDKVersion) {
|
2017-12-14 08:12:46 +08:00
|
|
|
OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
|
|
|
|
if (Update)
|
|
|
|
OS << ", " << Update;
|
2018-12-14 09:14:10 +08:00
|
|
|
EmitSDKVersionSuffix(OS, SDKVersion);
|
2017-12-14 08:12:46 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *getPlatformName(MachO::PlatformType Type) {
|
|
|
|
switch (Type) {
|
2018-12-21 01:51:17 +08:00
|
|
|
case MachO::PLATFORM_MACOS: return "macos";
|
|
|
|
case MachO::PLATFORM_IOS: return "ios";
|
|
|
|
case MachO::PLATFORM_TVOS: return "tvos";
|
|
|
|
case MachO::PLATFORM_WATCHOS: return "watchos";
|
|
|
|
case MachO::PLATFORM_BRIDGEOS: return "bridgeos";
|
2019-07-13 06:06:08 +08:00
|
|
|
case MachO::PLATFORM_MACCATALYST: return "macCatalyst";
|
2018-12-21 01:51:17 +08:00
|
|
|
case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator";
|
|
|
|
case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator";
|
|
|
|
case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
|
2020-08-15 03:34:20 +08:00
|
|
|
case MachO::PLATFORM_DRIVERKIT: return "driverkit";
|
2014-03-19 06:09:05 +08:00
|
|
|
}
|
2017-12-14 08:12:46 +08:00
|
|
|
llvm_unreachable("Invalid Mach-O platform type");
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
|
2018-12-14 09:14:10 +08:00
|
|
|
unsigned Minor, unsigned Update,
|
|
|
|
VersionTuple SDKVersion) {
|
2017-12-14 08:12:46 +08:00
|
|
|
const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
|
|
|
|
OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
|
2014-03-19 06:09:05 +08:00
|
|
|
if (Update)
|
|
|
|
OS << ", " << Update;
|
2018-12-14 09:14:10 +08:00
|
|
|
EmitSDKVersionSuffix(OS, SDKVersion);
|
2014-03-19 06:09:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
|
2010-11-06 06:08:08 +08:00
|
|
|
// This needs to emit to a temporary string to get properly quoted
|
|
|
|
// MCSymbols when they have spaces in them.
|
|
|
|
OS << "\t.thumb_func";
|
2011-05-17 00:17:21 +08:00
|
|
|
// Only Mach-O hasSubsectionsViaSymbols()
|
2015-06-09 08:31:39 +08:00
|
|
|
if (MAI->hasSubsectionsViaSymbols()) {
|
|
|
|
OS << '\t';
|
|
|
|
Func->print(OS, MAI);
|
|
|
|
}
|
2010-11-06 06:08:08 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
|
2018-06-05 23:13:39 +08:00
|
|
|
// Do not emit a .set on inlined target assignments.
|
|
|
|
bool EmitSet = true;
|
|
|
|
if (auto *E = dyn_cast<MCTargetExpr>(Value))
|
|
|
|
if (E->inlineAssignedExpr())
|
|
|
|
EmitSet = false;
|
|
|
|
if (EmitSet) {
|
|
|
|
OS << ".set ";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ", ";
|
|
|
|
Value->print(OS, MAI);
|
2015-06-09 08:31:39 +08:00
|
|
|
|
2018-06-05 23:13:39 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
2009-10-16 09:34:54 +08:00
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
MCStreamer::emitAssignment(Symbol, Value);
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << ".weakref ";
|
|
|
|
Alias->print(OS, MAI);
|
|
|
|
OS << ", ";
|
|
|
|
Symbol->print(OS, MAI);
|
2010-11-01 22:28:48 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
|
2020-11-03 04:32:06 +08:00
|
|
|
MCSymbolAttr Attribute) {
|
2009-06-24 09:03:06 +08:00
|
|
|
switch (Attribute) {
|
2012-02-07 13:05:23 +08:00
|
|
|
case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
|
2010-01-26 02:30:45 +08:00
|
|
|
case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function
|
|
|
|
case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
|
|
|
|
case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object
|
|
|
|
case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object
|
|
|
|
case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common
|
|
|
|
case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype
|
2010-11-13 12:55:06 +08:00
|
|
|
case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object
|
2013-08-09 09:52:03 +08:00
|
|
|
if (!MAI->hasDotTypeDotSizeDirective())
|
|
|
|
return false; // Symbol attribute not supported
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.type\t";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
|
2010-01-26 02:30:45 +08:00
|
|
|
switch (Attribute) {
|
2013-08-09 09:52:03 +08:00
|
|
|
default: return false;
|
2010-01-26 02:30:45 +08:00
|
|
|
case MCSA_ELF_TypeFunction: OS << "function"; break;
|
|
|
|
case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
|
|
|
|
case MCSA_ELF_TypeObject: OS << "object"; break;
|
|
|
|
case MCSA_ELF_TypeTLS: OS << "tls_object"; break;
|
|
|
|
case MCSA_ELF_TypeCommon: OS << "common"; break;
|
2018-02-09 21:34:39 +08:00
|
|
|
case MCSA_ELF_TypeNoType: OS << "notype"; break;
|
2010-11-13 12:55:06 +08:00
|
|
|
case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
|
2010-01-26 02:30:45 +08:00
|
|
|
}
|
|
|
|
EmitEOL();
|
2013-08-09 09:52:03 +08:00
|
|
|
return true;
|
2010-01-26 02:30:45 +08:00
|
|
|
case MCSA_Global: // .globl/.global
|
2013-06-18 15:20:20 +08:00
|
|
|
OS << MAI->getGlobalDirective();
|
2010-01-26 02:30:45 +08:00
|
|
|
break;
|
2019-09-27 03:38:32 +08:00
|
|
|
case MCSA_LGlobal: OS << "\t.lglobl\t"; break;
|
2010-06-22 04:35:01 +08:00
|
|
|
case MCSA_Hidden: OS << "\t.hidden\t"; break;
|
|
|
|
case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
|
|
|
|
case MCSA_Internal: OS << "\t.internal\t"; break;
|
|
|
|
case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;
|
|
|
|
case MCSA_Local: OS << "\t.local\t"; break;
|
2014-12-24 12:11:42 +08:00
|
|
|
case MCSA_NoDeadStrip:
|
|
|
|
if (!MAI->hasNoDeadStrip())
|
|
|
|
return false;
|
|
|
|
OS << "\t.no_dead_strip\t";
|
|
|
|
break;
|
2010-11-20 02:39:33 +08:00
|
|
|
case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
|
2016-03-15 09:43:05 +08:00
|
|
|
case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;
|
2011-05-01 00:34:57 +08:00
|
|
|
case MCSA_PrivateExtern:
|
|
|
|
OS << "\t.private_extern\t";
|
|
|
|
break;
|
2010-06-22 04:35:01 +08:00
|
|
|
case MCSA_Protected: OS << "\t.protected\t"; break;
|
|
|
|
case MCSA_Reference: OS << "\t.reference\t"; break;
|
2020-04-30 21:53:41 +08:00
|
|
|
case MCSA_Extern:
|
|
|
|
OS << "\t.extern\t";
|
|
|
|
break;
|
2014-12-02 05:16:17 +08:00
|
|
|
case MCSA_Weak: OS << MAI->getWeakDirective(); break;
|
2011-05-01 00:34:57 +08:00
|
|
|
case MCSA_WeakDefinition:
|
|
|
|
OS << "\t.weak_definition\t";
|
|
|
|
break;
|
2010-01-23 14:39:22 +08:00
|
|
|
// .weak_reference
|
2013-06-18 15:20:20 +08:00
|
|
|
case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
|
2010-07-09 01:22:42 +08:00
|
|
|
case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
|
2019-01-26 02:30:22 +08:00
|
|
|
case MCSA_Cold:
|
|
|
|
// Assemblers currently do not support a .cold directive.
|
|
|
|
return false;
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2015-06-09 08:31:39 +08:00
|
|
|
Symbol->print(OS, MAI);
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2013-08-09 09:52:03 +08:00
|
|
|
|
|
|
|
return true;
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << ".desc" << ' ';
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ',' << DescValue;
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-07-15 02:17:10 +08:00
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitSyntaxDirective() {
|
2016-07-11 20:42:14 +08:00
|
|
|
if (MAI->getAssemblerDialect() == 1) {
|
|
|
|
OS << "\t.intel_syntax noprefix";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
2015-07-22 18:49:44 +08:00
|
|
|
// FIXME: Currently emit unprefix'ed registers.
|
2018-07-31 03:41:25 +08:00
|
|
|
// The intel_syntax directive has one optional argument
|
2015-07-22 18:49:44 +08:00
|
|
|
// with may have a value of prefix or noprefix.
|
|
|
|
}
|
|
|
|
|
2010-05-09 03:54:22 +08:00
|
|
|
void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.def\t ";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ';';
|
2010-05-09 03:54:22 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
|
|
|
|
OS << "\t.scl\t" << StorageClass << ';';
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
|
|
|
|
OS << "\t.type\t" << Type << ';';
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmStreamer::EndCOFFSymbolDef() {
|
|
|
|
OS << "\t.endef";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2015-05-30 12:56:02 +08:00
|
|
|
void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
|
2015-07-14 02:51:15 +08:00
|
|
|
OS << "\t.safeseh\t";
|
|
|
|
Symbol->print(OS, MAI);
|
2015-05-30 12:56:02 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2018-01-10 07:49:30 +08:00
|
|
|
void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
|
|
|
|
OS << "\t.symidx\t";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2013-12-21 02:15:00 +08:00
|
|
|
void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.secidx\t";
|
|
|
|
Symbol->print(OS, MAI);
|
2013-12-21 02:15:00 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-01-02 11:00:19 +08:00
|
|
|
void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.secrel32\t";
|
|
|
|
Symbol->print(OS, MAI);
|
2017-01-02 11:00:19 +08:00
|
|
|
if (Offset != 0)
|
|
|
|
OS << '+' << Offset;
|
2011-12-17 09:14:52 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2018-07-27 04:11:26 +08:00
|
|
|
void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
|
|
|
|
OS << "\t.rva\t";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
if (Offset > 0)
|
|
|
|
OS << '+' << Offset;
|
|
|
|
else if (Offset < 0)
|
|
|
|
OS << '-' << -Offset;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2019-08-14 01:04:51 +08:00
|
|
|
// We need an XCOFF-specific version of this directive as the AIX syntax
|
Enable assembly output of local commons for AIX
Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
llvm-svn: 368306
2019-08-08 23:40:35 +08:00
|
|
|
// requires a QualName argument identifying the csect name and storage mapping
|
|
|
|
// class to appear before the alignment if we are specifying it.
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
|
[XCOFF][AIX] Differentiate usage of label symbol and csect symbol
Summary:
We are using symbols to represent label and csect interchangeably before, and that could be a problem.
There are cases we would need to add storage mapping class to the symbol if that symbol is actually the name of a csect, but it's hard for us to figure out whether that symbol is a label or csect.
This patch intend to do the following:
1. Construct a QualName (A name include the storage mapping class)
MCSymbolXCOFF for every MCSectionXCOFF.
2. Keep a pointer to that QualName inside of MCSectionXCOFF.
3. Use that QualName whenever we need a symbol refers to that
MCSectionXCOFF.
4. Adapt the snowball effect from the above changes in
XCOFFObjectWriter.cpp.
Reviewers: xingxue, DiggerLin, sfertile, daltenty, hubert.reinterpretcast
Reviewed By: DiggerLin, daltenty
Subscribers: wuzish, nemanjai, mgorny, hiraditya, kbarton, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69633
2019-11-08 22:26:28 +08:00
|
|
|
uint64_t Size,
|
|
|
|
MCSymbol *CsectSym,
|
Enable assembly output of local commons for AIX
Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
llvm-svn: 368306
2019-08-08 23:40:35 +08:00
|
|
|
unsigned ByteAlignment) {
|
|
|
|
assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
|
2019-08-14 01:04:51 +08:00
|
|
|
"We only support writing log base-2 alignment format with XCOFF.");
|
|
|
|
assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
|
Enable assembly output of local commons for AIX
Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
llvm-svn: 368306
2019-08-08 23:40:35 +08:00
|
|
|
|
|
|
|
OS << "\t.lcomm\t";
|
[XCOFF][AIX] Differentiate usage of label symbol and csect symbol
Summary:
We are using symbols to represent label and csect interchangeably before, and that could be a problem.
There are cases we would need to add storage mapping class to the symbol if that symbol is actually the name of a csect, but it's hard for us to figure out whether that symbol is a label or csect.
This patch intend to do the following:
1. Construct a QualName (A name include the storage mapping class)
MCSymbolXCOFF for every MCSectionXCOFF.
2. Keep a pointer to that QualName inside of MCSectionXCOFF.
3. Use that QualName whenever we need a symbol refers to that
MCSectionXCOFF.
4. Adapt the snowball effect from the above changes in
XCOFFObjectWriter.cpp.
Reviewers: xingxue, DiggerLin, sfertile, daltenty, hubert.reinterpretcast
Reviewed By: DiggerLin, daltenty
Subscribers: wuzish, nemanjai, mgorny, hiraditya, kbarton, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D69633
2019-11-08 22:26:28 +08:00
|
|
|
LabelSym->print(OS, MAI);
|
|
|
|
OS << ',' << Size << ',';
|
|
|
|
CsectSym->print(OS, MAI);
|
Enable assembly output of local commons for AIX
Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
llvm-svn: 368306
2019-08-08 23:40:35 +08:00
|
|
|
OS << ',' << Log2_32(ByteAlignment);
|
|
|
|
|
|
|
|
EmitEOL();
|
2020-08-18 22:18:53 +08:00
|
|
|
|
|
|
|
// Print symbol's rename (original name contains invalid character(s)) if
|
|
|
|
// there is one.
|
|
|
|
MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);
|
|
|
|
if (XSym->hasRename())
|
|
|
|
emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
|
Enable assembly output of local commons for AIX
Summary:
This patch enable assembly output of local commons for AIX using .lcomm
directives. Adds a EmitXCOFFLocalCommonSymbol to MCStreamer so we can emit the
AIX version of .lcomm assembly directives which include a csect name. Handle the
case of BSS locals in PPCAIXAsmPrinter by using EmitXCOFFLocalCommonSymbol. Adds
a test for generating .lcomm on AIX Targets.
Reviewers: cebowleratibm, hubert.reinterpretcast, Xiangling_L, jasonliu, sfertile
Reviewed By: sfertile
Subscribers: wuzish, nemanjai, hiraditya, kbarton, MaskRay, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64825
llvm-svn: 368306
2019-08-08 23:40:35 +08:00
|
|
|
}
|
|
|
|
|
[AIX] supporting the visibility attribute for aix assembly
SUMMARY:
in the aix assembly , it do not have .hidden and .protected directive.
in current llvm. if a function or a variable which has visibility attribute, it will generate something like the .hidden or .protected , it can not recognize by aix as.
in aix assembly, the visibility attribute are support in the pseudo-op like
.extern Name [ , Visibility ]
.globl Name [, Visibility ]
.weak Name [, Visibility ]
in this patch, we implement the visibility attribute for the global variable, function or extern function .
for example.
extern __attribute__ ((visibility ("hidden"))) int
bar(int* ip);
__attribute__ ((visibility ("hidden"))) int b = 0;
__attribute__ ((visibility ("hidden"))) int
foo(int* ip){
return (*ip)++;
}
the visibility of .comm linkage do not support , we will have a separate patch for it.
we have the unsupported cases ("default" and "internal") , we will implement them in a a separate patch for it.
Reviewers: Jason Liu ,hubert.reinterpretcast,James Henderson
Differential Revision: https://reviews.llvm.org/D75866
2020-06-10 04:15:06 +08:00
|
|
|
void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
|
|
|
|
MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
|
|
|
|
|
|
|
|
switch (Linkage) {
|
|
|
|
case MCSA_Global:
|
|
|
|
OS << MAI->getGlobalDirective();
|
|
|
|
break;
|
|
|
|
case MCSA_Weak:
|
|
|
|
OS << MAI->getWeakDirective();
|
|
|
|
break;
|
|
|
|
case MCSA_Extern:
|
|
|
|
OS << "\t.extern\t";
|
|
|
|
break;
|
2020-07-06 22:18:06 +08:00
|
|
|
case MCSA_LGlobal:
|
|
|
|
OS << "\t.lglobl\t";
|
|
|
|
break;
|
[AIX] supporting the visibility attribute for aix assembly
SUMMARY:
in the aix assembly , it do not have .hidden and .protected directive.
in current llvm. if a function or a variable which has visibility attribute, it will generate something like the .hidden or .protected , it can not recognize by aix as.
in aix assembly, the visibility attribute are support in the pseudo-op like
.extern Name [ , Visibility ]
.globl Name [, Visibility ]
.weak Name [, Visibility ]
in this patch, we implement the visibility attribute for the global variable, function or extern function .
for example.
extern __attribute__ ((visibility ("hidden"))) int
bar(int* ip);
__attribute__ ((visibility ("hidden"))) int b = 0;
__attribute__ ((visibility ("hidden"))) int
foo(int* ip){
return (*ip)++;
}
the visibility of .comm linkage do not support , we will have a separate patch for it.
we have the unsupported cases ("default" and "internal") , we will implement them in a a separate patch for it.
Reviewers: Jason Liu ,hubert.reinterpretcast,James Henderson
Differential Revision: https://reviews.llvm.org/D75866
2020-06-10 04:15:06 +08:00
|
|
|
default:
|
|
|
|
report_fatal_error("unhandled linkage type");
|
|
|
|
}
|
|
|
|
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
|
|
|
|
switch (Visibility) {
|
|
|
|
case MCSA_Invalid:
|
|
|
|
// Nothing to do.
|
|
|
|
break;
|
|
|
|
case MCSA_Hidden:
|
|
|
|
OS << ",hidden";
|
|
|
|
break;
|
|
|
|
case MCSA_Protected:
|
|
|
|
OS << ",protected";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
report_fatal_error("unexpected value for Visibility type");
|
|
|
|
}
|
|
|
|
EmitEOL();
|
2020-08-10 21:46:46 +08:00
|
|
|
|
|
|
|
// Print symbol's rename (original name contains invalid character(s)) if
|
|
|
|
// there is one.
|
|
|
|
if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
|
|
|
|
emitXCOFFRenameDirective(Symbol,
|
|
|
|
cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
|
[AIX] supporting the visibility attribute for aix assembly
SUMMARY:
in the aix assembly , it do not have .hidden and .protected directive.
in current llvm. if a function or a variable which has visibility attribute, it will generate something like the .hidden or .protected , it can not recognize by aix as.
in aix assembly, the visibility attribute are support in the pseudo-op like
.extern Name [ , Visibility ]
.globl Name [, Visibility ]
.weak Name [, Visibility ]
in this patch, we implement the visibility attribute for the global variable, function or extern function .
for example.
extern __attribute__ ((visibility ("hidden"))) int
bar(int* ip);
__attribute__ ((visibility ("hidden"))) int b = 0;
__attribute__ ((visibility ("hidden"))) int
foo(int* ip){
return (*ip)++;
}
the visibility of .comm linkage do not support , we will have a separate patch for it.
we have the unsupported cases ("default" and "internal") , we will implement them in a a separate patch for it.
Reviewers: Jason Liu ,hubert.reinterpretcast,James Henderson
Differential Revision: https://reviews.llvm.org/D75866
2020-06-10 04:15:06 +08:00
|
|
|
}
|
|
|
|
|
2020-07-06 22:18:06 +08:00
|
|
|
void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
|
|
|
|
StringRef Rename) {
|
|
|
|
OS << "\t.rename\t";
|
|
|
|
Name->print(OS, MAI);
|
|
|
|
const char DQ = '"';
|
|
|
|
OS << ',' << DQ;
|
|
|
|
for (char C : Rename) {
|
|
|
|
// To escape a double quote character, the character should be doubled.
|
|
|
|
if (C == DQ)
|
|
|
|
OS << DQ;
|
|
|
|
OS << C;
|
|
|
|
}
|
|
|
|
OS << DQ;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2016-12-02 07:39:08 +08:00
|
|
|
void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
|
2013-06-18 15:20:20 +08:00
|
|
|
assert(MAI->hasDotTypeDotSizeDirective());
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.size\t";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ", ";
|
|
|
|
Value->print(OS, MAI);
|
2016-07-18 23:24:03 +08:00
|
|
|
EmitEOL();
|
2010-01-25 15:52:13 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
2009-08-30 14:17:16 +08:00
|
|
|
unsigned ByteAlignment) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.comm\t";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ',' << Size;
|
|
|
|
|
2010-01-25 15:29:13 +08:00
|
|
|
if (ByteAlignment != 0) {
|
2013-06-18 15:20:20 +08:00
|
|
|
if (MAI->getCOMMDirectiveAlignmentIsInBytes())
|
2010-01-19 14:01:04 +08:00
|
|
|
OS << ',' << ByteAlignment;
|
|
|
|
else
|
|
|
|
OS << ',' << Log2_32(ByteAlignment);
|
|
|
|
}
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2020-08-10 21:46:46 +08:00
|
|
|
|
|
|
|
// Print symbol's rename (original name contains invalid character(s)) if
|
|
|
|
// there is one.
|
|
|
|
MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
|
|
|
|
if (XSym && XSym->hasRename())
|
|
|
|
emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
|
|
|
|
|
2009-07-08 04:30:46 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
2011-09-02 07:04:27 +08:00
|
|
|
unsigned ByteAlign) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.lcomm\t";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ',' << Size;
|
|
|
|
|
2011-09-02 07:04:27 +08:00
|
|
|
if (ByteAlign > 1) {
|
2013-06-18 15:20:20 +08:00
|
|
|
switch (MAI->getLCOMMDirectiveAlignmentType()) {
|
2012-09-08 05:08:01 +08:00
|
|
|
case LCOMM::NoAlignment:
|
|
|
|
llvm_unreachable("alignment not supported on .lcomm!");
|
|
|
|
case LCOMM::ByteAlignment:
|
2012-09-08 01:25:13 +08:00
|
|
|
OS << ',' << ByteAlign;
|
2012-09-08 05:08:01 +08:00
|
|
|
break;
|
|
|
|
case LCOMM::Log2Alignment:
|
2012-09-08 01:25:13 +08:00
|
|
|
assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
|
|
|
|
OS << ',' << Log2_32(ByteAlign);
|
2012-09-08 05:08:01 +08:00
|
|
|
break;
|
2012-09-08 01:25:13 +08:00
|
|
|
}
|
2011-09-02 07:04:27 +08:00
|
|
|
}
|
2010-01-23 15:47:02 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
|
2018-07-03 01:29:43 +08:00
|
|
|
uint64_t Size, unsigned ByteAlignment,
|
|
|
|
SMLoc Loc) {
|
2013-09-20 07:21:01 +08:00
|
|
|
if (Symbol)
|
2015-10-05 20:07:05 +08:00
|
|
|
AssignFragment(Symbol, &Section->getDummyFragment());
|
2013-09-20 07:21:01 +08:00
|
|
|
|
2009-08-14 07:36:34 +08:00
|
|
|
// Note: a .zerofill directive does not switch sections.
|
2009-08-09 07:39:42 +08:00
|
|
|
OS << ".zerofill ";
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2018-07-03 01:29:43 +08:00
|
|
|
assert(Section->getVariant() == MCSection::SV_MachO &&
|
|
|
|
".zerofill is a Mach-O specific directive");
|
2009-08-09 07:39:42 +08:00
|
|
|
// This is a mach-o specific directive.
|
2018-07-03 01:29:43 +08:00
|
|
|
|
2009-08-10 09:39:42 +08:00
|
|
|
const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
|
2020-04-16 06:49:05 +08:00
|
|
|
OS << MOSection->getSegmentName() << "," << MOSection->getName();
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2014-04-13 12:57:38 +08:00
|
|
|
if (Symbol) {
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << ',';
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ',' << Size;
|
2009-08-30 14:17:16 +08:00
|
|
|
if (ByteAlignment != 0)
|
|
|
|
OS << ',' << Log2_32(ByteAlignment);
|
2009-07-11 06:20:30 +08:00
|
|
|
}
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-07-11 06:20:30 +08:00
|
|
|
}
|
|
|
|
|
2010-05-17 10:13:02 +08:00
|
|
|
// .tbss sym, size, align
|
|
|
|
// This depends that the symbol has already been mangled from the original,
|
|
|
|
// e.g. _a.
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
|
2010-05-19 05:16:04 +08:00
|
|
|
uint64_t Size, unsigned ByteAlignment) {
|
2015-10-05 20:07:05 +08:00
|
|
|
AssignFragment(Symbol, &Section->getDummyFragment());
|
2013-09-20 07:21:01 +08:00
|
|
|
|
2014-04-13 12:57:38 +08:00
|
|
|
assert(Symbol && "Symbol shouldn't be NULL!");
|
2010-05-19 05:16:04 +08:00
|
|
|
// Instead of using the Section we'll just use the shortcut.
|
2018-07-03 01:29:43 +08:00
|
|
|
|
|
|
|
assert(Section->getVariant() == MCSection::SV_MachO &&
|
|
|
|
".zerofill is a Mach-O specific directive");
|
2010-05-19 05:16:04 +08:00
|
|
|
// This is a mach-o specific directive and section.
|
2018-07-03 01:29:43 +08:00
|
|
|
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << ".tbss ";
|
|
|
|
Symbol->print(OS, MAI);
|
|
|
|
OS << ", " << Size;
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-05-19 05:16:04 +08:00
|
|
|
// Output align if we have it. We default to 1 so don't bother printing
|
|
|
|
// that.
|
|
|
|
if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-05-14 09:50:28 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2010-01-23 08:15:00 +08:00
|
|
|
static inline char toOctal(int X) { return (X&7)+'0'; }
|
|
|
|
|
2020-09-30 09:11:16 +08:00
|
|
|
static void PrintByteList(StringRef Data, raw_ostream &OS,
|
|
|
|
MCAsmInfo::AsmCharLiteralSyntax ACLS) {
|
|
|
|
assert(!Data.empty() && "Cannot generate an empty list.");
|
|
|
|
const auto printCharacterInOctal = [&OS](unsigned char C) {
|
|
|
|
OS << '0';
|
|
|
|
OS << toOctal(C >> 6);
|
|
|
|
OS << toOctal(C >> 3);
|
|
|
|
OS << toOctal(C >> 0);
|
|
|
|
};
|
|
|
|
const auto printOneCharacterFor = [printCharacterInOctal](
|
|
|
|
auto printOnePrintingCharacter) {
|
|
|
|
return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
|
|
|
|
if (isPrint(C)) {
|
|
|
|
printOnePrintingCharacter(static_cast<char>(C));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
printCharacterInOctal(C);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
|
|
|
|
const auto BeginPtr = Data.begin(), EndPtr = Data.end();
|
|
|
|
for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
|
|
|
|
printOneCharacter(C);
|
|
|
|
OS << ',';
|
|
|
|
}
|
|
|
|
printOneCharacter(*(EndPtr - 1));
|
|
|
|
};
|
|
|
|
switch (ACLS) {
|
|
|
|
case MCAsmInfo::ACLS_Unknown:
|
|
|
|
printCharacterList(printCharacterInOctal);
|
|
|
|
return;
|
|
|
|
case MCAsmInfo::ACLS_SingleQuotePrefix:
|
|
|
|
printCharacterList(printOneCharacterFor([&OS](char C) {
|
|
|
|
const char AsmCharLitBuf[2] = {'\'', C};
|
|
|
|
OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
|
|
|
|
}));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
llvm_unreachable("Invalid AsmCharLiteralSyntax value!");
|
|
|
|
}
|
|
|
|
|
2010-01-26 02:58:59 +08:00
|
|
|
static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
|
|
|
|
OS << '"';
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-26 02:58:59 +08:00
|
|
|
for (unsigned i = 0, e = Data.size(); i != e; ++i) {
|
|
|
|
unsigned char C = Data[i];
|
|
|
|
if (C == '"' || C == '\\') {
|
|
|
|
OS << '\\' << (char)C;
|
|
|
|
continue;
|
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2018-07-26 23:31:41 +08:00
|
|
|
if (isPrint((unsigned char)C)) {
|
2010-01-26 02:58:59 +08:00
|
|
|
OS << (char)C;
|
|
|
|
continue;
|
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-26 02:58:59 +08:00
|
|
|
switch (C) {
|
|
|
|
case '\b': OS << "\\b"; break;
|
|
|
|
case '\f': OS << "\\f"; break;
|
|
|
|
case '\n': OS << "\\n"; break;
|
|
|
|
case '\r': OS << "\\r"; break;
|
|
|
|
case '\t': OS << "\\t"; break;
|
|
|
|
default:
|
|
|
|
OS << '\\';
|
|
|
|
OS << toOctal(C >> 6);
|
|
|
|
OS << toOctal(C >> 3);
|
|
|
|
OS << toOctal(C >> 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-26 02:58:59 +08:00
|
|
|
OS << '"';
|
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitBytes(StringRef Data) {
|
2016-10-14 13:47:37 +08:00
|
|
|
assert(getCurrentSectionOnly() &&
|
2013-04-18 05:18:16 +08:00
|
|
|
"Cannot emit contents before setting section!");
|
2010-01-23 08:15:00 +08:00
|
|
|
if (Data.empty()) return;
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2020-09-30 09:11:16 +08:00
|
|
|
const auto emitAsString = [this](StringRef Data) {
|
|
|
|
// If the data ends with 0 and the target supports .asciz, use it, otherwise
|
|
|
|
// use .ascii or a byte-list directive
|
|
|
|
if (MAI->getAscizDirective() && Data.back() == 0) {
|
|
|
|
OS << MAI->getAscizDirective();
|
|
|
|
Data = Data.substr(0, Data.size() - 1);
|
|
|
|
} else if (LLVM_LIKELY(MAI->getAsciiDirective())) {
|
|
|
|
OS << MAI->getAsciiDirective();
|
|
|
|
} else if (MAI->getByteListDirective()) {
|
|
|
|
OS << MAI->getByteListDirective();
|
|
|
|
PrintByteList(Data, OS, MAI->characterLiteralSyntax());
|
|
|
|
EmitEOL();
|
|
|
|
return true;
|
[DEBUGINFO, NVPTX] Try to pack bytes data into a single string.
Summary:
If the target does not support `.asciz` and `.ascii` directives, the
strings are represented as bytes and each byte is placed on the new line
as a separate byte directive `.b8 <data>`. NVPTX target allows to
represent the vector of the data of the same type as a vector, where
values are separated using `,` symbol: `.b8 <data1>,<data2>,...`. This
allows to reduce the size of the final PTX file. Ptxas tool includes ptx
files into the resulting binary object, so reducing the size of the PTX
file is important.
Reviewers: tra, jlebar, echristo
Subscribers: jholewinski, llvm-commits
Differential Revision: https://reviews.llvm.org/D45822
llvm-svn: 345142
2018-10-24 22:04:00 +08:00
|
|
|
} else {
|
2020-09-30 09:11:16 +08:00
|
|
|
return false;
|
2017-12-20 22:55:10 +08:00
|
|
|
}
|
2020-09-30 09:11:16 +08:00
|
|
|
|
|
|
|
PrintQuotedString(Data, OS);
|
|
|
|
EmitEOL();
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (Data.size() != 1 && emitAsString(Data))
|
2010-01-23 08:15:00 +08:00
|
|
|
return;
|
|
|
|
|
2020-09-30 09:11:16 +08:00
|
|
|
// Only single byte is provided or no ascii, asciz, or byte-list directives
|
|
|
|
// are applicable. Emit as vector of individual 8bits data elements.
|
|
|
|
if (MCTargetStreamer *TS = getTargetStreamer()) {
|
|
|
|
TS->emitRawBytes(Data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const char *Directive = MAI->getData8bitsDirective();
|
|
|
|
for (const unsigned char C : Data.bytes()) {
|
|
|
|
OS << Directive << (unsigned)C;
|
|
|
|
EmitEOL();
|
2010-01-23 08:15:00 +08:00
|
|
|
}
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 10:16:24 +08:00
|
|
|
void MCAsmStreamer::emitBinaryData(StringRef Data) {
|
[codeview] Improve readability of type record assembly
Adds the method MCStreamer::EmitBinaryData, which is usually an alias
for EmitBytes. In the MCAsmStreamer case, it is overridden to emit hex
dump output like this:
.byte 0x0e, 0x00, 0x08, 0x10
.byte 0x03, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x10, 0x00, 0x00
Also, when verbose asm comments are enabled, this patch prints the dump
output for each comment before its record, like this:
# ArgList (0x1000) {
# TypeLeafKind: LF_ARGLIST (0x1201)
# NumArgs: 0
# Arguments [
# ]
# }
.byte 0x06, 0x00, 0x01, 0x12
.byte 0x00, 0x00, 0x00, 0x00
This should make debugging easier and testing more convenient.
Reviewers: aaboud
Subscribers: majnemer, zturner, amccarth, aaboud, llvm-commits
Differential Revision: http://reviews.llvm.org/D20711
llvm-svn: 271313
2016-06-01 02:45:36 +08:00
|
|
|
// This is binary data. Print it in a grid of hex bytes for readability.
|
|
|
|
const size_t Cols = 4;
|
|
|
|
for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
|
|
|
|
size_t J = I, EJ = std::min(I + Cols, Data.size());
|
|
|
|
assert(EJ > 0);
|
|
|
|
OS << MAI->getData8bitsDirective();
|
|
|
|
for (; J < EJ - 1; ++J)
|
|
|
|
OS << format("0x%02x", uint8_t(Data[J])) << ", ";
|
|
|
|
OS << format("0x%02x", uint8_t(Data[J]));
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-15 14:40:47 +08:00
|
|
|
void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
|
|
|
|
emitValue(MCConstantExpr::create(Value, getContext()), Size);
|
2010-12-03 10:54:21 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 14:40:47 +08:00
|
|
|
void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
|
|
|
|
emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
|
2019-07-18 07:43:58 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 14:40:47 +08:00
|
|
|
void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
|
2020-02-07 00:12:10 +08:00
|
|
|
unsigned Size) {
|
2020-02-15 14:40:47 +08:00
|
|
|
emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
|
2020-02-07 00:12:10 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
|
2015-09-21 07:35:59 +08:00
|
|
|
SMLoc Loc) {
|
2014-02-01 15:19:38 +08:00
|
|
|
assert(Size <= 8 && "Invalid size");
|
2016-10-14 13:47:37 +08:00
|
|
|
assert(getCurrentSectionOnly() &&
|
2013-04-18 05:18:16 +08:00
|
|
|
"Cannot emit contents before setting section!");
|
2014-04-13 12:57:38 +08:00
|
|
|
const char *Directive = nullptr;
|
2010-01-20 06:03:38 +08:00
|
|
|
switch (Size) {
|
|
|
|
default: break;
|
2013-07-02 23:49:13 +08:00
|
|
|
case 1: Directive = MAI->getData8bitsDirective(); break;
|
|
|
|
case 2: Directive = MAI->getData16bitsDirective(); break;
|
|
|
|
case 4: Directive = MAI->getData32bitsDirective(); break;
|
2014-02-01 15:19:38 +08:00
|
|
|
case 8: Directive = MAI->getData64bitsDirective(); break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Directive) {
|
2010-11-29 07:22:44 +08:00
|
|
|
int64_t IntValue;
|
2015-05-30 09:25:56 +08:00
|
|
|
if (!Value->evaluateAsAbsolute(IntValue))
|
2010-11-29 07:22:44 +08:00
|
|
|
report_fatal_error("Don't know how to emit this value.");
|
2014-02-01 15:19:38 +08:00
|
|
|
|
|
|
|
// We couldn't handle the requested integer size so we fallback by breaking
|
2016-02-02 04:36:49 +08:00
|
|
|
// the request down into several, smaller, integers.
|
|
|
|
// Since sizes greater or equal to "Size" are invalid, we use the greatest
|
|
|
|
// power of 2 that is less than "Size" as our largest piece of granularity.
|
2014-02-01 15:19:38 +08:00
|
|
|
bool IsLittleEndian = MAI->isLittleEndian();
|
|
|
|
for (unsigned Emitted = 0; Emitted != Size;) {
|
|
|
|
unsigned Remaining = Size - Emitted;
|
|
|
|
// The size of our partial emission must be a power of two less than
|
2016-02-02 04:36:49 +08:00
|
|
|
// Size.
|
|
|
|
unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
|
2014-02-01 15:19:38 +08:00
|
|
|
// Calculate the byte offset of our partial emission taking into account
|
|
|
|
// the endianness of the target.
|
|
|
|
unsigned ByteOffset =
|
|
|
|
IsLittleEndian ? Emitted : (Remaining - EmissionSize);
|
|
|
|
uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
|
|
|
|
// We truncate our partial emission to fit within the bounds of the
|
|
|
|
// emission domain. This produces nicer output and silences potential
|
|
|
|
// truncation warnings when round tripping through another assembler.
|
2014-12-13 05:48:03 +08:00
|
|
|
uint64_t Shift = 64 - EmissionSize * 8;
|
2014-12-15 22:25:12 +08:00
|
|
|
assert(Shift < static_cast<uint64_t>(
|
2014-12-14 00:55:02 +08:00
|
|
|
std::numeric_limits<unsigned long long>::digits) &&
|
2014-12-13 05:48:03 +08:00
|
|
|
"undefined behavior");
|
|
|
|
ValueToEmit &= ~0ULL >> Shift;
|
2020-02-15 14:40:47 +08:00
|
|
|
emitIntValue(ValueToEmit, EmissionSize);
|
2014-02-01 15:19:38 +08:00
|
|
|
Emitted += EmissionSize;
|
2010-01-20 14:45:39 +08:00
|
|
|
}
|
|
|
|
return;
|
2010-01-20 06:03:38 +08:00
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2010-01-20 06:03:38 +08:00
|
|
|
assert(Directive && "Invalid size for machine code value!");
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << Directive;
|
2017-12-20 22:55:10 +08:00
|
|
|
if (MCTargetStreamer *TS = getTargetStreamer()) {
|
|
|
|
TS->emitValue(Value);
|
|
|
|
} else {
|
|
|
|
Value->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 05:26:21 +08:00
|
|
|
void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
|
2010-11-19 12:10:13 +08:00
|
|
|
int64_t IntValue;
|
2015-05-30 09:25:56 +08:00
|
|
|
if (Value->evaluateAsAbsolute(IntValue)) {
|
2020-02-14 05:26:21 +08:00
|
|
|
emitULEB128IntValue(IntValue);
|
2010-11-19 12:10:13 +08:00
|
|
|
return;
|
|
|
|
}
|
2018-02-10 01:00:25 +08:00
|
|
|
OS << "\t.uleb128 ";
|
2015-06-09 08:31:39 +08:00
|
|
|
Value->print(OS, MAI);
|
2010-11-03 01:22:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 05:26:21 +08:00
|
|
|
void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
|
2010-11-19 12:10:13 +08:00
|
|
|
int64_t IntValue;
|
2015-05-30 09:25:56 +08:00
|
|
|
if (Value->evaluateAsAbsolute(IntValue)) {
|
2020-02-14 05:26:21 +08:00
|
|
|
emitSLEB128IntValue(IntValue);
|
2010-11-19 12:10:13 +08:00
|
|
|
return;
|
|
|
|
}
|
2018-02-10 01:00:25 +08:00
|
|
|
OS << "\t.sleb128 ";
|
2015-06-09 08:31:39 +08:00
|
|
|
Value->print(OS, MAI);
|
2010-11-03 01:22:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
|
2016-08-23 00:18:42 +08:00
|
|
|
assert(MAI->getDTPRel64Directive() != nullptr);
|
|
|
|
OS << MAI->getDTPRel64Directive();
|
|
|
|
Value->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
|
2016-08-23 00:18:42 +08:00
|
|
|
assert(MAI->getDTPRel32Directive() != nullptr);
|
|
|
|
OS << MAI->getDTPRel32Directive();
|
|
|
|
Value->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
|
2016-08-23 00:18:42 +08:00
|
|
|
assert(MAI->getTPRel64Directive() != nullptr);
|
|
|
|
OS << MAI->getTPRel64Directive();
|
|
|
|
Value->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
|
2016-08-23 00:18:42 +08:00
|
|
|
assert(MAI->getTPRel32Directive() != nullptr);
|
|
|
|
OS << MAI->getTPRel32Directive();
|
|
|
|
Value->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
|
2014-04-13 12:57:38 +08:00
|
|
|
assert(MAI->getGPRel64Directive() != nullptr);
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << MAI->getGPRel64Directive();
|
|
|
|
Value->print(OS, MAI);
|
2012-02-03 12:33:00 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
|
2014-04-13 12:57:38 +08:00
|
|
|
assert(MAI->getGPRel32Directive() != nullptr);
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << MAI->getGPRel32Directive();
|
|
|
|
Value->print(OS, MAI);
|
2010-01-26 05:28:50 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2016-05-28 13:57:48 +08:00
|
|
|
void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
|
|
|
|
SMLoc Loc) {
|
2018-01-10 03:29:33 +08:00
|
|
|
int64_t IntNumBytes;
|
[AIX] Don't use a zero fill with a second parameter
Summary:
The AIX assembler .space directive can't take a second non-zero argument to fill
with. But LLVM emitFill currently assumes it can. We add a flag to the AsmInfo
to check if non-zero fill is supported, and if we can't zerofill non-zero values
we just splat the .byte directives.
Reviewers: stevewan, sfertile, DiggerLin, jasonliu, Xiangling_L
Reviewed By: jasonliu
Subscribers: Xiangling_L, wuzish, nemanjai, hiraditya, kbarton, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D73554
2020-02-04 04:14:08 +08:00
|
|
|
const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
|
|
|
|
if (IsAbsolute && IntNumBytes == 0)
|
2018-01-10 03:29:33 +08:00
|
|
|
return;
|
|
|
|
|
2013-07-02 23:49:13 +08:00
|
|
|
if (const char *ZeroDirective = MAI->getZeroDirective()) {
|
[AIX] Don't use a zero fill with a second parameter
Summary:
The AIX assembler .space directive can't take a second non-zero argument to fill
with. But LLVM emitFill currently assumes it can. We add a flag to the AsmInfo
to check if non-zero fill is supported, and if we can't zerofill non-zero values
we just splat the .byte directives.
Reviewers: stevewan, sfertile, DiggerLin, jasonliu, Xiangling_L
Reviewed By: jasonliu
Subscribers: Xiangling_L, wuzish, nemanjai, hiraditya, kbarton, jsji, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D73554
2020-02-04 04:14:08 +08:00
|
|
|
if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
|
|
|
|
// FIXME: Emit location directives
|
|
|
|
OS << ZeroDirective;
|
|
|
|
NumBytes.print(OS, MAI);
|
|
|
|
if (FillValue != 0)
|
|
|
|
OS << ',' << (int)FillValue;
|
|
|
|
EmitEOL();
|
|
|
|
} else {
|
|
|
|
if (!IsAbsolute)
|
|
|
|
report_fatal_error(
|
|
|
|
"Cannot emit non-absolute expression lengths of fill.");
|
|
|
|
for (int i = 0; i < IntNumBytes; ++i) {
|
|
|
|
OS << MAI->getData8bitsDirective() << (int)FillValue;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
}
|
2013-07-02 23:49:13 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-01-20 03:46:13 +08:00
|
|
|
|
2016-05-28 13:57:48 +08:00
|
|
|
MCStreamer::emitFill(NumBytes, FillValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
|
|
|
|
int64_t Expr, SMLoc Loc) {
|
|
|
|
// FIXME: Emit location directives
|
|
|
|
OS << "\t.fill\t";
|
|
|
|
NumValues.print(OS, MAI);
|
|
|
|
OS << ", " << Size << ", 0x";
|
|
|
|
OS.write_hex(truncateToSize(Expr, 4));
|
|
|
|
EmitEOL();
|
2010-01-20 02:52:28 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
|
2009-06-25 03:25:34 +08:00
|
|
|
unsigned ValueSize,
|
|
|
|
unsigned MaxBytesToEmit) {
|
[PowerPC][AIX] Adds support for writing the .data section in assembly files
Summary:
Adds support for generating the .data section in assembly files for global variables with a non-zero initialization. The support for writing the .data section in XCOFF object files will be added in a follow-on patch. Any relocations are not included in this patch.
Reviewers: hubert.reinterpretcast, sfertile, jasonliu, daltenty, Xiangling_L
Reviewed by: hubert.reinterpretcast
Subscribers: nemanjai, hiraditya, kbarton, MaskRay, jsji, wuzish, shchenz, DiggerLin, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D66154
llvm-svn: 369869
2019-08-25 23:17:25 +08:00
|
|
|
if (MAI->useDotAlignForAlignment()) {
|
|
|
|
if (!isPowerOf2_32(ByteAlignment))
|
|
|
|
report_fatal_error("Only power-of-two alignments are supported "
|
|
|
|
"with .align.");
|
|
|
|
OS << "\t.align\t";
|
|
|
|
OS << Log2_32(ByteAlignment);
|
|
|
|
EmitEOL();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-19 14:12:02 +08:00
|
|
|
// Some assemblers don't support non-power of two alignments, so we always
|
|
|
|
// emit alignments as a power of two if possible.
|
|
|
|
if (isPowerOf2_32(ByteAlignment)) {
|
2009-08-19 14:35:36 +08:00
|
|
|
switch (ValueSize) {
|
2014-02-05 02:39:51 +08:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Invalid size for machine code value!");
|
|
|
|
case 1:
|
2016-01-26 08:03:25 +08:00
|
|
|
OS << "\t.p2align\t";
|
2014-02-05 02:39:51 +08:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
OS << ".p2alignw ";
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
OS << ".p2alignl ";
|
|
|
|
break;
|
|
|
|
case 8:
|
|
|
|
llvm_unreachable("Unsupported alignment size!");
|
2009-08-19 14:35:36 +08:00
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2016-01-26 08:03:25 +08:00
|
|
|
OS << Log2_32(ByteAlignment);
|
2009-08-19 14:12:02 +08:00
|
|
|
|
|
|
|
if (Value || MaxBytesToEmit) {
|
2009-09-03 12:01:10 +08:00
|
|
|
OS << ", 0x";
|
|
|
|
OS.write_hex(truncateToSize(Value, ValueSize));
|
2009-06-25 03:25:34 +08:00
|
|
|
|
2010-09-23 02:16:55 +08:00
|
|
|
if (MaxBytesToEmit)
|
2009-08-19 14:12:02 +08:00
|
|
|
OS << ", " << MaxBytesToEmit;
|
|
|
|
}
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-08-19 14:12:02 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-09-23 02:16:55 +08:00
|
|
|
|
2009-08-19 14:12:02 +08:00
|
|
|
// Non-power of two alignment. This is not widely supported by assemblers.
|
2009-08-23 05:43:10 +08:00
|
|
|
// FIXME: Parameterize this based on MAI.
|
2009-06-25 03:25:34 +08:00
|
|
|
switch (ValueSize) {
|
2009-08-19 14:12:02 +08:00
|
|
|
default: llvm_unreachable("Invalid size for machine code value!");
|
|
|
|
case 1: OS << ".balign"; break;
|
|
|
|
case 2: OS << ".balignw"; break;
|
|
|
|
case 4: OS << ".balignl"; break;
|
|
|
|
case 8: llvm_unreachable("Unsupported alignment size!");
|
2009-06-25 03:25:34 +08:00
|
|
|
}
|
|
|
|
|
2009-08-19 14:12:02 +08:00
|
|
|
OS << ' ' << ByteAlignment;
|
2009-06-26 05:03:18 +08:00
|
|
|
OS << ", " << truncateToSize(Value, ValueSize);
|
2010-09-23 02:16:55 +08:00
|
|
|
if (MaxBytesToEmit)
|
2009-06-25 03:25:34 +08:00
|
|
|
OS << ", " << MaxBytesToEmit;
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-06-25 03:25:34 +08:00
|
|
|
}
|
|
|
|
|
2020-02-15 11:21:58 +08:00
|
|
|
void MCAsmStreamer::emitCodeAlignment(unsigned ByteAlignment,
|
2010-02-24 02:26:34 +08:00
|
|
|
unsigned MaxBytesToEmit) {
|
2010-02-24 02:44:31 +08:00
|
|
|
// Emit with a text fill value.
|
2020-02-15 11:21:58 +08:00
|
|
|
emitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
|
2010-02-24 02:44:31 +08:00
|
|
|
1, MaxBytesToEmit);
|
2010-02-24 02:26:34 +08:00
|
|
|
}
|
|
|
|
|
2015-11-05 07:59:18 +08:00
|
|
|
void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
|
2016-12-14 18:43:58 +08:00
|
|
|
unsigned char Value,
|
|
|
|
SMLoc Loc) {
|
2009-06-25 03:25:34 +08:00
|
|
|
// FIXME: Verify that Offset is associated with the current section.
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << ".org ";
|
|
|
|
Offset->print(OS, MAI);
|
|
|
|
OS << ", " << (unsigned)Value;
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-06-25 03:25:34 +08:00
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitFileDirective(StringRef Filename) {
|
2013-06-18 15:20:20 +08:00
|
|
|
assert(MAI->hasSingleParameterDotFile());
|
2010-01-26 02:58:59 +08:00
|
|
|
OS << "\t.file\t";
|
|
|
|
PrintQuotedString(Filename, OS);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2018-03-30 01:16:41 +08:00
|
|
|
static void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
|
|
|
|
StringRef Filename,
|
2019-04-05 07:34:38 +08:00
|
|
|
Optional<MD5::MD5Result> Checksum,
|
2018-03-30 01:16:41 +08:00
|
|
|
Optional<StringRef> Source,
|
|
|
|
bool UseDwarfDirectory,
|
|
|
|
raw_svector_ostream &OS) {
|
2014-03-18 02:13:58 +08:00
|
|
|
SmallString<128> FullPathName;
|
|
|
|
|
2011-10-18 07:05:28 +08:00
|
|
|
if (!UseDwarfDirectory && !Directory.empty()) {
|
|
|
|
if (sys::path::is_absolute(Filename))
|
2014-03-18 02:13:58 +08:00
|
|
|
Directory = "";
|
|
|
|
else {
|
|
|
|
FullPathName = Directory;
|
|
|
|
sys::path::append(FullPathName, Filename);
|
|
|
|
Directory = "";
|
|
|
|
Filename = FullPathName;
|
|
|
|
}
|
2011-10-18 07:05:28 +08:00
|
|
|
}
|
|
|
|
|
2018-03-30 01:16:41 +08:00
|
|
|
OS << "\t.file\t" << FileNo << ' ';
|
2014-02-06 02:00:21 +08:00
|
|
|
if (!Directory.empty()) {
|
2018-03-30 01:16:41 +08:00
|
|
|
PrintQuotedString(Directory, OS);
|
|
|
|
OS << ' ';
|
2017-12-20 22:55:10 +08:00
|
|
|
}
|
2018-03-30 01:16:41 +08:00
|
|
|
PrintQuotedString(Filename, OS);
|
2018-04-11 23:14:05 +08:00
|
|
|
if (Checksum)
|
|
|
|
OS << " md5 0x" << Checksum->digest();
|
2018-02-24 07:01:06 +08:00
|
|
|
if (Source) {
|
2018-03-30 01:16:41 +08:00
|
|
|
OS << " source ";
|
|
|
|
PrintQuotedString(*Source, OS);
|
2018-02-24 07:01:06 +08:00
|
|
|
}
|
2018-03-30 01:16:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
|
|
|
|
unsigned FileNo, StringRef Directory, StringRef Filename,
|
2019-04-05 07:34:38 +08:00
|
|
|
Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) {
|
2018-03-30 01:16:41 +08:00
|
|
|
assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
|
|
|
|
|
|
|
|
MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
|
|
|
|
unsigned NumFiles = Table.getMCDwarfFiles().size();
|
|
|
|
Expected<unsigned> FileNoOrErr =
|
[llvm] Prevent duplicate files in debug line header in dwarf 5: another attempt
Another attempt to land the changes in debug line header to prevent duplicate
files in Dwarf 5. I rolled back my previous commit because of a mistake in
generating the object file in a test. Meanwhile, I addressed some offline
comments and changed the implementation; the largest difference is that
MCDwarfLineTableHeader does not keep DwarfVersion but gets it as a parameter. I
also merged the patch to fix two lld tests that will strt to fail into this
patch.
Original Commit:
https://reviews.llvm.org/D59515
Original Message:
Motivation: In previous dwarf versions, file name indexes started from 1, and
the primary source file was not explicit. Dwarf 5 standard (6.2.4) prescribes
the primary source file to be explicitly given an entry with an index number 0.
The current implementation honors the specification by just duplicating the
main source file, once with index number 0, and later maybe with another
index number. While this is compliant with the letter of the standard, the
duplication causes problems for consumers of this information such as lldb.
(Some files are duplicated, where only some of them have a line table although
all refer to the same file)
With this change, dwarf 5 debug line section files always start from 0, and
the zeroth entry is not duplicated whenever possible. This requires different
handling of dwarf 4 and dwarf 5 during generation (e.g. when a function returns
an index zero for a file name, it signals an error in dwarf 4, but not in dwarf
5) However, I think the minor complication is worth it, because it enables all
consumers (lldb, gdb, dwarfdump, objdump, and so on) to treat all files in the
file name list homogenously.
llvm-svn: 358732
2019-04-19 10:26:56 +08:00
|
|
|
Table.tryGetFile(Directory, Filename, Checksum, Source,
|
|
|
|
getContext().getDwarfVersion(), FileNo);
|
2018-03-30 01:16:41 +08:00
|
|
|
if (!FileNoOrErr)
|
|
|
|
return FileNoOrErr.takeError();
|
|
|
|
FileNo = FileNoOrErr.get();
|
|
|
|
if (NumFiles == Table.getMCDwarfFiles().size())
|
|
|
|
return FileNo;
|
|
|
|
|
|
|
|
SmallString<128> Str;
|
|
|
|
raw_svector_ostream OS1(Str);
|
|
|
|
printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
|
|
|
|
UseDwarfDirectory, OS1);
|
|
|
|
|
|
|
|
if (MCTargetStreamer *TS = getTargetStreamer())
|
2017-12-20 22:55:10 +08:00
|
|
|
TS->emitDwarfFileDirective(OS1.str());
|
2018-03-30 01:16:41 +08:00
|
|
|
else
|
2020-02-16 00:52:56 +08:00
|
|
|
emitRawText(OS1.str());
|
2014-02-06 02:00:21 +08:00
|
|
|
|
2014-03-18 02:13:58 +08:00
|
|
|
return FileNo;
|
2010-11-17 05:20:32 +08:00
|
|
|
}
|
|
|
|
|
2018-03-30 01:16:41 +08:00
|
|
|
void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
|
|
|
|
StringRef Filename,
|
2019-04-05 07:34:38 +08:00
|
|
|
Optional<MD5::MD5Result> Checksum,
|
2018-03-30 01:16:41 +08:00
|
|
|
Optional<StringRef> Source,
|
|
|
|
unsigned CUID) {
|
|
|
|
assert(CUID == 0);
|
|
|
|
// .file 0 is new for DWARF v5.
|
|
|
|
if (getContext().getDwarfVersion() < 5)
|
|
|
|
return;
|
2018-06-14 21:38:20 +08:00
|
|
|
// Inform MCDwarf about the root file.
|
|
|
|
getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
|
|
|
|
Source);
|
2018-03-30 01:16:41 +08:00
|
|
|
|
|
|
|
SmallString<128> Str;
|
|
|
|
raw_svector_ostream OS1(Str);
|
|
|
|
printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
|
|
|
|
UseDwarfDirectory, OS1);
|
|
|
|
|
|
|
|
if (MCTargetStreamer *TS = getTargetStreamer())
|
|
|
|
TS->emitDwarfFileDirective(OS1.str());
|
|
|
|
else
|
2020-02-16 00:52:56 +08:00
|
|
|
emitRawText(OS1.str());
|
2018-03-30 01:16:41 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 05:26:21 +08:00
|
|
|
void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
|
2010-11-17 05:20:32 +08:00
|
|
|
unsigned Column, unsigned Flags,
|
2020-02-14 05:26:21 +08:00
|
|
|
unsigned Isa, unsigned Discriminator,
|
2011-04-19 04:26:49 +08:00
|
|
|
StringRef FileName) {
|
2010-11-17 05:20:32 +08:00
|
|
|
OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
|
2018-04-04 01:28:55 +08:00
|
|
|
if (MAI->supportsExtendedDwarfLocDirective()) {
|
|
|
|
if (Flags & DWARF2_FLAG_BASIC_BLOCK)
|
|
|
|
OS << " basic_block";
|
|
|
|
if (Flags & DWARF2_FLAG_PROLOGUE_END)
|
|
|
|
OS << " prologue_end";
|
|
|
|
if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
|
|
|
|
OS << " epilogue_begin";
|
|
|
|
|
|
|
|
unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
|
|
|
|
if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
|
|
|
|
OS << " is_stmt ";
|
|
|
|
|
|
|
|
if (Flags & DWARF2_FLAG_IS_STMT)
|
|
|
|
OS << "1";
|
|
|
|
else
|
|
|
|
OS << "0";
|
|
|
|
}
|
2010-11-17 05:20:32 +08:00
|
|
|
|
2018-04-04 01:28:55 +08:00
|
|
|
if (Isa)
|
|
|
|
OS << " isa " << Isa;
|
|
|
|
if (Discriminator)
|
|
|
|
OS << " discriminator " << Discriminator;
|
|
|
|
}
|
2011-04-19 04:26:49 +08:00
|
|
|
|
|
|
|
if (IsVerboseAsm) {
|
2013-06-18 15:20:20 +08:00
|
|
|
OS.PadToColumn(MAI->getCommentColumn());
|
|
|
|
OS << MAI->getCommentString() << ' ' << FileName << ':'
|
2011-04-19 04:26:49 +08:00
|
|
|
<< Line << ':' << Column;
|
|
|
|
}
|
2010-11-17 05:20:32 +08:00
|
|
|
EmitEOL();
|
2020-02-14 05:26:21 +08:00
|
|
|
this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
|
|
|
|
Discriminator, FileName);
|
2010-01-26 02:58:59 +08:00
|
|
|
}
|
|
|
|
|
2014-04-01 16:07:52 +08:00
|
|
|
MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
|
|
|
|
// Always use the zeroth line table, since asm syntax only supports one line
|
|
|
|
// table for now.
|
|
|
|
return MCStreamer::getDwarfLineTableSymbol(0);
|
|
|
|
}
|
|
|
|
|
2017-09-20 02:14:45 +08:00
|
|
|
bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
|
|
|
|
ArrayRef<uint8_t> Checksum,
|
|
|
|
unsigned ChecksumKind) {
|
|
|
|
if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
|
|
|
|
ChecksumKind))
|
2016-08-27 01:58:37 +08:00
|
|
|
return false;
|
2016-01-29 08:49:42 +08:00
|
|
|
|
|
|
|
OS << "\t.cv_file\t" << FileNo << ' ';
|
2017-09-16 09:14:36 +08:00
|
|
|
PrintQuotedString(Filename, OS);
|
2017-09-20 02:14:45 +08:00
|
|
|
|
|
|
|
if (!ChecksumKind) {
|
|
|
|
EmitEOL();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << ' ';
|
|
|
|
PrintQuotedString(toHex(Checksum), OS);
|
|
|
|
OS << ' ' << ChecksumKind;
|
|
|
|
|
2016-01-29 08:49:42 +08:00
|
|
|
EmitEOL();
|
2016-08-27 01:58:37 +08:00
|
|
|
return true;
|
2016-01-29 08:49:42 +08:00
|
|
|
}
|
|
|
|
|
2016-09-08 00:15:31 +08:00
|
|
|
bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
|
|
|
|
OS << "\t.cv_func_id " << FuncId << '\n';
|
|
|
|
return MCStreamer::EmitCVFuncIdDirective(FuncId);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
|
|
|
|
unsigned IAFunc,
|
|
|
|
unsigned IAFile,
|
|
|
|
unsigned IALine, unsigned IACol,
|
|
|
|
SMLoc Loc) {
|
|
|
|
OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
|
|
|
|
<< " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
|
|
|
|
return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
|
|
|
|
IALine, IACol, Loc);
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
|
2016-01-29 08:49:42 +08:00
|
|
|
unsigned Line, unsigned Column,
|
|
|
|
bool PrologueEnd, bool IsStmt,
|
2016-09-08 00:15:31 +08:00
|
|
|
StringRef FileName, SMLoc Loc) {
|
2018-08-29 07:25:59 +08:00
|
|
|
// Validate the directive.
|
|
|
|
if (!checkCVLocSection(FunctionId, FileNo, Loc))
|
|
|
|
return;
|
|
|
|
|
2016-01-29 08:49:42 +08:00
|
|
|
OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
|
|
|
|
<< Column;
|
|
|
|
if (PrologueEnd)
|
|
|
|
OS << " prologue_end";
|
|
|
|
|
2018-08-29 07:25:59 +08:00
|
|
|
if (IsStmt)
|
|
|
|
OS << " is_stmt 1";
|
2016-01-29 08:49:42 +08:00
|
|
|
|
|
|
|
if (IsVerboseAsm) {
|
|
|
|
OS.PadToColumn(MAI->getCommentColumn());
|
2016-09-08 00:15:31 +08:00
|
|
|
OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
|
|
|
|
<< Column;
|
2016-01-29 08:49:42 +08:00
|
|
|
}
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
|
2016-01-29 08:49:42 +08:00
|
|
|
const MCSymbol *FnStart,
|
|
|
|
const MCSymbol *FnEnd) {
|
|
|
|
OS << "\t.cv_linetable\t" << FunctionId << ", ";
|
|
|
|
FnStart->print(OS, MAI);
|
|
|
|
OS << ", ";
|
|
|
|
FnEnd->print(OS, MAI);
|
|
|
|
EmitEOL();
|
2020-04-21 10:28:13 +08:00
|
|
|
this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
|
2016-01-29 08:49:42 +08:00
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
|
2016-09-08 00:15:31 +08:00
|
|
|
unsigned SourceFileId,
|
|
|
|
unsigned SourceLineNum,
|
|
|
|
const MCSymbol *FnStartSym,
|
|
|
|
const MCSymbol *FnEndSym) {
|
2016-01-30 03:24:12 +08:00
|
|
|
OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
|
2016-02-03 01:41:18 +08:00
|
|
|
<< ' ' << SourceLineNum << ' ';
|
|
|
|
FnStartSym->print(OS, MAI);
|
2016-02-03 03:22:34 +08:00
|
|
|
OS << ' ';
|
|
|
|
FnEndSym->print(OS, MAI);
|
2016-01-30 03:24:12 +08:00
|
|
|
EmitEOL();
|
2020-04-21 10:28:13 +08:00
|
|
|
this->MCStreamer::emitCVInlineLinetableDirective(
|
2016-09-08 00:15:31 +08:00
|
|
|
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
|
2016-01-30 03:24:12 +08:00
|
|
|
}
|
|
|
|
|
2019-08-05 22:16:58 +08:00
|
|
|
void MCAsmStreamer::PrintCVDefRangePrefix(
|
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
|
2016-02-05 09:55:49 +08:00
|
|
|
OS << "\t.cv_def_range\t";
|
|
|
|
for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
|
|
|
|
OS << ' ';
|
|
|
|
Range.first->print(OS, MAI);
|
|
|
|
OS << ' ';
|
|
|
|
Range.second->print(OS, MAI);
|
|
|
|
}
|
2019-08-05 22:16:58 +08:00
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeRegisterRelHeader DRHdr) {
|
2019-08-05 22:16:58 +08:00
|
|
|
PrintCVDefRangePrefix(Ranges);
|
|
|
|
OS << ", reg_rel, ";
|
|
|
|
OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
|
|
|
|
<< DRHdr.BasePointerOffset;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeSubfieldRegisterHeader DRHdr) {
|
2019-08-05 22:16:58 +08:00
|
|
|
PrintCVDefRangePrefix(Ranges);
|
|
|
|
OS << ", subfield_reg, ";
|
|
|
|
OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeRegisterHeader DRHdr) {
|
2019-08-05 22:16:58 +08:00
|
|
|
PrintCVDefRangePrefix(Ranges);
|
|
|
|
OS << ", reg, ";
|
|
|
|
OS << DRHdr.Register;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVDefRangeDirective(
|
2019-08-05 22:16:58 +08:00
|
|
|
ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
|
2019-10-19 09:44:09 +08:00
|
|
|
codeview::DefRangeFramePointerRelHeader DRHdr) {
|
2019-08-05 22:16:58 +08:00
|
|
|
PrintCVDefRangePrefix(Ranges);
|
|
|
|
OS << ", frame_ptr_rel, ";
|
|
|
|
OS << DRHdr.Offset;
|
2016-02-05 09:55:49 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVStringTableDirective() {
|
2016-01-29 08:49:42 +08:00
|
|
|
OS << "\t.cv_stringtable";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVFileChecksumsDirective() {
|
2016-01-29 08:49:42 +08:00
|
|
|
OS << "\t.cv_filechecksums";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
|
2017-09-20 02:14:45 +08:00
|
|
|
OS << "\t.cv_filechecksumoffset\t" << FileNo;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
[codeview] Implement FPO data assembler directives
Summary:
This adds a set of new directives that describe 32-bit x86 prologues.
The directives are limited and do not expose the full complexity of
codeview FPO data. They are merely a convenience for the compiler to
generate more readable assembly so we don't need to generate tons of
labels in CodeGen. If our prologue emission changes in the future, we
can change the set of available directives to suit our needs. These are
modelled after the .seh_ directives, which use a different format that
interacts with exception handling.
The directives are:
.cv_fpo_proc _foo
.cv_fpo_pushreg ebp/ebx/etc
.cv_fpo_setframe ebp/esi/etc
.cv_fpo_stackalloc 200
.cv_fpo_endprologue
.cv_fpo_endproc
.cv_fpo_data _foo
I tried to follow the implementation of ARM EHABI CFI directives by
sinking most directives out of MCStreamer and into X86TargetStreamer.
This helps avoid polluting non-X86 code with WinCOFF specific logic.
I used cdb to confirm that this can show locals in parent CSRs in a few
cases, most importantly the one where we use ESI as a frame pointer,
i.e. the one in http://crbug.com/756153#c28
Once we have cdb integration in debuginfo-tests, we can add integration
tests there.
Reviewers: majnemer, hans
Subscribers: aemerson, mgorny, kristof.beyls, llvm-commits, hiraditya
Differential Revision: https://reviews.llvm.org/D38776
llvm-svn: 315513
2017-10-12 05:24:33 +08:00
|
|
|
void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
|
|
|
|
OS << "\t.cv_fpo_data\t";
|
|
|
|
ProcSym->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitIdent(StringRef IdentString) {
|
2013-10-16 09:05:45 +08:00
|
|
|
assert(MAI->hasIdentDirective() && ".ident directive not supported");
|
|
|
|
OS << "\t.ident\t";
|
|
|
|
PrintQuotedString(IdentString, OS);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
|
|
|
|
MCStreamer::emitCFISections(EH, Debug);
|
2011-05-10 21:39:48 +08:00
|
|
|
OS << "\t.cfi_sections ";
|
|
|
|
if (EH) {
|
|
|
|
OS << ".eh_frame";
|
|
|
|
if (Debug)
|
|
|
|
OS << ", .debug_frame";
|
|
|
|
} else if (Debug) {
|
|
|
|
OS << ".debug_frame";
|
|
|
|
}
|
|
|
|
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
|
2011-01-15 05:57:39 +08:00
|
|
|
OS << "\t.cfi_startproc";
|
2014-01-28 01:20:25 +08:00
|
|
|
if (Frame.IsSimple)
|
|
|
|
OS << " simple";
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
|
|
|
|
MCStreamer::emitCFIEndProcImpl(Frame);
|
2011-01-15 05:57:39 +08:00
|
|
|
OS << "\t.cfi_endproc";
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
2011-04-13 07:59:07 +08:00
|
|
|
}
|
2010-11-22 22:27:24 +08:00
|
|
|
|
2011-05-31 04:20:15 +08:00
|
|
|
void MCAsmStreamer::EmitRegisterName(int64_t Register) {
|
2015-05-27 20:13:06 +08:00
|
|
|
if (!MAI->useDwarfRegNumForCFI()) {
|
2017-12-02 05:44:27 +08:00
|
|
|
// User .cfi_* directives can use arbitrary DWARF register numbers, not
|
|
|
|
// just ones that map to LLVM register numbers and have known names.
|
|
|
|
// Fall back to using the original number directly if no name is known.
|
2013-06-18 15:20:20 +08:00
|
|
|
const MCRegisterInfo *MRI = getContext().getRegisterInfo();
|
MCRegisterInfo: Merge getLLVMRegNum and getLLVMRegNumFromEH
Summary:
The functions different in two ways:
- getLLVMRegNum could return both "eh" and "other" dwarf register
numbers, while getLLVMRegNumFromEH only returned the "eh" number.
- getLLVMRegNum asserted if the register was not found, while the second
function returned -1.
The second distinction was pretty important, but it was very hard to
infer that from the function name. Aditionally, for the use case of
dumping dwarf expressions, we needed a function which can work with both
kinds of number, but does not assert.
This patch solves both of these issues by merging the two functions into
one, returning an Optional<unsigned> value. While the same thing could
be achieved by adding an "IsEH" argument to the (renamed)
getLLVMRegNumFromEH function, it seemed better to avoid the confusion of
two functions and put the choice of asserting into the hands of the
caller -- if he checks the Optional value, he can safely process
"untrusted" input, and if he blindly dereferences the Optional, he gets
the assertion.
I've updated all call sites to the new API, choosing between the two
options according to the function they were calling originally, except
that I've updated the usage in DWARFExpression.cpp to use the "safe"
method instead, and added a test case which would have previously
triggered an assertion failure when processing (incorrect?) dwarf
expressions.
Reviewers: dsanders, arsenm, JDevlieghere
Subscribers: wdng, aprantl, javed.absar, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67154
llvm-svn: 372710
2019-09-24 17:31:02 +08:00
|
|
|
if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) {
|
|
|
|
InstPrinter->printRegName(OS, *LLVMRegister);
|
2017-12-02 05:44:27 +08:00
|
|
|
return;
|
|
|
|
}
|
2011-05-31 04:20:15 +08:00
|
|
|
}
|
2017-12-02 05:44:27 +08:00
|
|
|
OS << Register;
|
2011-05-31 04:20:15 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
|
|
|
|
MCStreamer::emitCFIDefCfa(Register, Offset);
|
2011-05-31 04:20:15 +08:00
|
|
|
OS << "\t.cfi_def_cfa ";
|
|
|
|
EmitRegisterName(Register);
|
|
|
|
OS << ", " << Offset;
|
2011-04-30 05:41:06 +08:00
|
|
|
EmitEOL();
|
2010-11-22 22:27:24 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) {
|
|
|
|
MCStreamer::emitCFIDefCfaOffset(Offset);
|
2011-01-15 05:57:39 +08:00
|
|
|
OS << "\t.cfi_def_cfa_offset " << Offset;
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2015-10-07 15:01:31 +08:00
|
|
|
static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
|
|
|
|
OS << "\t.cfi_escape ";
|
|
|
|
if (!Values.empty()) {
|
|
|
|
size_t e = Values.size() - 1;
|
|
|
|
for (size_t i = 0; i < e; ++i)
|
|
|
|
OS << format("0x%02x", uint8_t(Values[i])) << ", ";
|
|
|
|
OS << format("0x%02x", uint8_t(Values[e]));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIEscape(StringRef Values) {
|
|
|
|
MCStreamer::emitCFIEscape(Values);
|
2015-10-07 15:01:31 +08:00
|
|
|
PrintCFIEscape(OS, Values);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) {
|
|
|
|
MCStreamer::emitCFIGnuArgsSize(Size);
|
2016-07-18 23:24:03 +08:00
|
|
|
|
2015-10-07 15:01:31 +08:00
|
|
|
uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
|
|
|
|
unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
|
2016-07-18 23:24:03 +08:00
|
|
|
|
2015-10-07 15:01:31 +08:00
|
|
|
PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) {
|
|
|
|
MCStreamer::emitCFIDefCfaRegister(Register);
|
2011-05-31 04:20:15 +08:00
|
|
|
OS << "\t.cfi_def_cfa_register ";
|
|
|
|
EmitRegisterName(Register);
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
|
|
|
|
this->MCStreamer::emitCFIOffset(Register, Offset);
|
2011-05-31 04:20:15 +08:00
|
|
|
OS << "\t.cfi_offset ";
|
|
|
|
EmitRegisterName(Register);
|
|
|
|
OS << ", " << Offset;
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
|
2010-12-27 08:36:05 +08:00
|
|
|
unsigned Encoding) {
|
2020-02-14 13:58:16 +08:00
|
|
|
MCStreamer::emitCFIPersonality(Sym, Encoding);
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.cfi_personality " << Encoding << ", ";
|
|
|
|
Sym->print(OS, MAI);
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
|
|
|
|
MCStreamer::emitCFILsda(Sym, Encoding);
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.cfi_lsda " << Encoding << ", ";
|
|
|
|
Sym->print(OS, MAI);
|
2010-11-22 22:27:24 +08:00
|
|
|
EmitEOL();
|
2011-04-13 07:59:07 +08:00
|
|
|
}
|
2010-11-22 22:27:24 +08:00
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIRememberState() {
|
|
|
|
MCStreamer::emitCFIRememberState();
|
2011-04-13 07:59:07 +08:00
|
|
|
OS << "\t.cfi_remember_state";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIRestoreState() {
|
|
|
|
MCStreamer::emitCFIRestoreState();
|
2011-04-13 07:59:07 +08:00
|
|
|
OS << "\t.cfi_restore_state";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIRestore(int64_t Register) {
|
|
|
|
MCStreamer::emitCFIRestore(Register);
|
2017-11-02 20:00:58 +08:00
|
|
|
OS << "\t.cfi_restore ";
|
|
|
|
EmitRegisterName(Register);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFISameValue(int64_t Register) {
|
|
|
|
MCStreamer::emitCFISameValue(Register);
|
2011-05-31 04:20:15 +08:00
|
|
|
OS << "\t.cfi_same_value ";
|
|
|
|
EmitRegisterName(Register);
|
2011-04-13 07:59:07 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
|
|
|
|
MCStreamer::emitCFIRelOffset(Register, Offset);
|
2011-05-31 04:20:15 +08:00
|
|
|
OS << "\t.cfi_rel_offset ";
|
|
|
|
EmitRegisterName(Register);
|
|
|
|
OS << ", " << Offset;
|
2011-04-13 07:59:07 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
|
|
|
|
MCStreamer::emitCFIAdjustCfaOffset(Adjustment);
|
2011-04-13 07:59:07 +08:00
|
|
|
OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
|
|
|
|
EmitEOL();
|
2010-11-22 22:27:24 +08:00
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFISignalFrame() {
|
|
|
|
MCStreamer::emitCFISignalFrame();
|
2012-05-31 08:53:18 +08:00
|
|
|
OS << "\t.cfi_signal_frame";
|
2012-01-24 05:51:52 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIUndefined(int64_t Register) {
|
|
|
|
MCStreamer::emitCFIUndefined(Register);
|
2020-02-25 22:01:26 +08:00
|
|
|
OS << "\t.cfi_undefined ";
|
|
|
|
EmitRegisterName(Register);
|
2012-11-24 00:59:41 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
|
|
|
|
MCStreamer::emitCFIRegister(Register1, Register2);
|
2020-02-25 22:01:26 +08:00
|
|
|
OS << "\t.cfi_register ";
|
|
|
|
EmitRegisterName(Register1);
|
|
|
|
OS << ", ";
|
|
|
|
EmitRegisterName(Register2);
|
2012-11-25 23:14:49 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIWindowSave() {
|
|
|
|
MCStreamer::emitCFIWindowSave();
|
2013-09-26 22:49:40 +08:00
|
|
|
OS << "\t.cfi_window_save";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFINegateRAState() {
|
|
|
|
MCStreamer::emitCFINegateRAState();
|
2018-12-18 18:37:42 +08:00
|
|
|
OS << "\t.cfi_negate_ra_state";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
|
|
|
|
MCStreamer::emitCFIReturnColumn(Register);
|
2020-02-25 22:01:26 +08:00
|
|
|
OS << "\t.cfi_return_column ";
|
|
|
|
EmitRegisterName(Register);
|
2017-07-28 11:39:19 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitCFIBKeyFrame() {
|
|
|
|
MCStreamer::emitCFIBKeyFrame();
|
2018-12-21 18:45:08 +08:00
|
|
|
OS << "\t.cfi_b_key_frame";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << ".seh_proc ";
|
|
|
|
Symbol->print(OS, MAI);
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIEndProc(Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_endproc";
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2018-10-27 14:13:06 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
|
[AArch64] Generate and parse SEH assembly directives
This ensures that you get the same output regardless if generating
code directly to an object file or if generating assembly and
assembling that.
Add implementations of the EmitARM64WinCFI*() methods in
AArch64TargetAsmStreamer, and fill in one blank in MCAsmStreamer.
Add corresponding directive handlers in AArch64AsmParser and
COFFAsmParser.
Some SEH directive names have been picked to match the prior art
for SEH assembly directives for x86_64, e.g. the spelling of
".seh_startepilogue" matching the preexisting ".seh_endprologue".
For the directives for saving registers, the exact spelling
from the arm64 documentation is picked, e.g. ".seh_save_reg" (to follow
that naming for all the other ones, e.g. ".seh_save_fregp_x"), while
the corresponding one for x86_64 is plain ".seh_savereg" without the
second underscore.
Directives in the epilogues have the same names as in prologues,
e.g. .seh_savereg, even though the registers are restored, not
saved, at that point.
Differential Revision: https://reviews.llvm.org/D86529
2020-08-07 17:44:48 +08:00
|
|
|
MCStreamer::EmitWinCFIFuncletOrFuncEnd(Loc);
|
|
|
|
|
|
|
|
OS << "\t.seh_endfunclet";
|
|
|
|
EmitEOL();
|
2018-10-27 14:13:06 +08:00
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIStartChained(Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_startchained";
|
2011-05-19 04:54:10 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIEndChained(Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_endchained";
|
2011-05-19 04:54:10 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2014-06-29 09:52:01 +08:00
|
|
|
void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
|
2017-10-10 09:26:25 +08:00
|
|
|
bool Except, SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2015-06-09 08:31:39 +08:00
|
|
|
OS << "\t.seh_handler ";
|
|
|
|
Sym->print(OS, MAI);
|
2011-05-20 01:46:39 +08:00
|
|
|
if (Unwind)
|
|
|
|
OS << ", @unwind";
|
|
|
|
if (Except)
|
|
|
|
OS << ", @except";
|
2011-05-19 04:54:10 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinEHHandlerData(Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-26 05:43:45 +08:00
|
|
|
// Switch sections. Don't call SwitchSection directly, because that will
|
|
|
|
// cause the section switch to be visible in the emitted assembly.
|
|
|
|
// We only do this so the section switch that terminates the handler
|
|
|
|
// data block is visible.
|
2014-08-04 02:51:17 +08:00
|
|
|
WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
|
2019-08-31 06:25:55 +08:00
|
|
|
|
|
|
|
// Do nothing if no frame is open. MCStreamer should've already reported an
|
|
|
|
// error.
|
|
|
|
if (!CurFrame)
|
|
|
|
return;
|
|
|
|
|
2016-05-03 07:22:18 +08:00
|
|
|
MCSection *TextSec = &CurFrame->Function->getSection();
|
|
|
|
MCSection *XData = getAssociatedXDataSection(TextSec);
|
2015-05-30 01:00:57 +08:00
|
|
|
SwitchSectionNoChange(XData);
|
2011-05-26 05:43:45 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_handlerdata";
|
2011-05-19 04:54:10 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
|
2017-10-10 09:26:25 +08:00
|
|
|
MCStreamer::EmitWinCFIPushReg(Register, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
OS << "\t.seh_pushreg ";
|
|
|
|
InstPrinter->printRegName(OS, Register);
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
|
2017-10-10 09:26:25 +08:00
|
|
|
SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
OS << "\t.seh_setframe ";
|
|
|
|
InstPrinter->printRegName(OS, Register);
|
|
|
|
OS << ", " << Offset;
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIAllocStack(Size, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_stackalloc " << Size;
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
|
2017-10-10 09:26:25 +08:00
|
|
|
SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
OS << "\t.seh_savereg ";
|
|
|
|
InstPrinter->printRegName(OS, Register);
|
|
|
|
OS << ", " << Offset;
|
2011-05-20 01:46:39 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
|
2017-10-10 09:26:25 +08:00
|
|
|
SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2019-08-31 05:23:05 +08:00
|
|
|
OS << "\t.seh_savexmm ";
|
|
|
|
InstPrinter->printRegName(OS, Register);
|
|
|
|
OS << ", " << Offset;
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIPushFrame(Code, Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_pushframe";
|
2011-05-18 12:58:05 +08:00
|
|
|
if (Code)
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << " @code";
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2017-10-10 09:26:25 +08:00
|
|
|
void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
|
|
|
|
MCStreamer::EmitWinCFIEndProlog(Loc);
|
2011-05-21 02:19:22 +08:00
|
|
|
|
2011-05-20 01:46:39 +08:00
|
|
|
OS << "\t.seh_endprologue";
|
2011-05-18 12:58:05 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
[MC] Add assembler support for .cg_profile.
Object FIle Representation
At codegen time this is emitted into the ELF file a pair of symbol indices and a weight. In assembly it looks like:
.cg_profile a, b, 32
.cg_profile freq, a, 11
.cg_profile freq, b, 20
When writing an ELF file these are put into a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight).
Differential Revision: https://reviews.llvm.org/D44965
llvm-svn: 333823
2018-06-03 00:33:01 +08:00
|
|
|
void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
|
|
|
|
const MCSymbolRefExpr *To,
|
|
|
|
uint64_t Count) {
|
|
|
|
OS << "\t.cg_profile ";
|
|
|
|
From->getSymbol().print(OS, MAI);
|
|
|
|
OS << ", ";
|
|
|
|
To->getSymbol().print(OS, MAI);
|
|
|
|
OS << ", " << Count;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2014-01-29 07:13:07 +08:00
|
|
|
void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
|
2019-02-04 20:51:26 +08:00
|
|
|
const MCSubtargetInfo &STI) {
|
2010-02-10 07:00:14 +08:00
|
|
|
raw_ostream &OS = GetCommentOS();
|
|
|
|
SmallString<256> Code;
|
|
|
|
SmallVector<MCFixup, 4> Fixups;
|
2014-06-27 06:52:05 +08:00
|
|
|
raw_svector_ostream VecOS(Code);
|
2018-04-27 23:45:54 +08:00
|
|
|
|
|
|
|
// If we have no code emitter, don't emit code.
|
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant
expressions. This improves the handing of preprocessor expressions
that must be resolved at parse time. This idiom can be found as
assembling-time assertion checks in source-level assemblers. Note that
this relies on the MCStreamer to keep sufficient tabs on Section /
Fragment information which the MCAsmStreamer does not. As a result the
textual output may fail where the equivalent object generation would
pass. This can most easily be resolved by folding the MCAsmStreamer
and MCObjectStreamer together which is planned for in a separate
patch.
Currently, this feature is only enabled for assembly input, keeping IR
compilation consistent between assembly and object generation.
Reviewers: echristo, rnk, probinson, espindola, peter.smith
Reviewed By: peter.smith
Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D45164
llvm-svn: 331218
2018-05-01 03:22:40 +08:00
|
|
|
if (!getAssembler().getEmitterPtr())
|
2018-04-27 23:45:54 +08:00
|
|
|
return;
|
|
|
|
|
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant
expressions. This improves the handing of preprocessor expressions
that must be resolved at parse time. This idiom can be found as
assembling-time assertion checks in source-level assemblers. Note that
this relies on the MCStreamer to keep sufficient tabs on Section /
Fragment information which the MCAsmStreamer does not. As a result the
textual output may fail where the equivalent object generation would
pass. This can most easily be resolved by folding the MCAsmStreamer
and MCObjectStreamer together which is planned for in a separate
patch.
Currently, this feature is only enabled for assembly input, keeping IR
compilation consistent between assembly and object generation.
Reviewers: echristo, rnk, probinson, espindola, peter.smith
Reviewed By: peter.smith
Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D45164
llvm-svn: 331218
2018-05-01 03:22:40 +08:00
|
|
|
getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
|
2010-01-26 02:58:59 +08:00
|
|
|
|
2010-02-10 07:00:14 +08:00
|
|
|
// If we are showing fixups, create symbolic markers in the encoded
|
|
|
|
// representation. We do this by making a per-bit map to the fixup item index,
|
|
|
|
// then trying to display it as nicely as possible.
|
2010-02-10 09:41:14 +08:00
|
|
|
SmallVector<uint8_t, 64> FixupMap;
|
|
|
|
FixupMap.resize(Code.size() * 8);
|
2010-02-10 07:00:14 +08:00
|
|
|
for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
|
|
|
|
FixupMap[i] = 0;
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
|
|
|
|
MCFixup &F = Fixups[i];
|
2018-04-27 23:45:54 +08:00
|
|
|
const MCFixupKindInfo &Info =
|
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant
expressions. This improves the handing of preprocessor expressions
that must be resolved at parse time. This idiom can be found as
assembling-time assertion checks in source-level assemblers. Note that
this relies on the MCStreamer to keep sufficient tabs on Section /
Fragment information which the MCAsmStreamer does not. As a result the
textual output may fail where the equivalent object generation would
pass. This can most easily be resolved by folding the MCAsmStreamer
and MCObjectStreamer together which is planned for in a separate
patch.
Currently, this feature is only enabled for assembly input, keeping IR
compilation consistent between assembly and object generation.
Reviewers: echristo, rnk, probinson, espindola, peter.smith
Reviewed By: peter.smith
Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D45164
llvm-svn: 331218
2018-05-01 03:22:40 +08:00
|
|
|
getAssembler().getBackend().getFixupKindInfo(F.getKind());
|
2010-02-10 07:00:14 +08:00
|
|
|
for (unsigned j = 0; j != Info.TargetSize; ++j) {
|
|
|
|
unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
|
|
|
|
assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
|
|
|
|
FixupMap[Index] = 1 + i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-09 06:49:42 +08:00
|
|
|
// FIXME: Note the fixup comments for Thumb2 are completely bogus since the
|
2011-01-14 07:27:39 +08:00
|
|
|
// high order halfword of a 32-bit Thumb2 instruction is emitted first.
|
2010-02-10 07:00:14 +08:00
|
|
|
OS << "encoding: [";
|
|
|
|
for (unsigned i = 0, e = Code.size(); i != e; ++i) {
|
|
|
|
if (i)
|
|
|
|
OS << ',';
|
|
|
|
|
|
|
|
// See if all bits are the same map entry.
|
|
|
|
uint8_t MapEntry = FixupMap[i * 8 + 0];
|
|
|
|
for (unsigned j = 1; j != 8; ++j) {
|
|
|
|
if (FixupMap[i * 8 + j] == MapEntry)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
MapEntry = uint8_t(~0U);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MapEntry != uint8_t(~0U)) {
|
|
|
|
if (MapEntry == 0) {
|
|
|
|
OS << format("0x%02x", uint8_t(Code[i]));
|
|
|
|
} else {
|
2011-01-14 05:45:26 +08:00
|
|
|
if (Code[i]) {
|
2011-01-14 07:27:39 +08:00
|
|
|
// FIXME: Some of the 8 bits require fix up.
|
2011-01-14 05:45:26 +08:00
|
|
|
OS << format("0x%02x", uint8_t(Code[i])) << '\''
|
|
|
|
<< char('A' + MapEntry - 1) << '\'';
|
|
|
|
} else
|
|
|
|
OS << char('A' + MapEntry - 1);
|
2010-02-10 07:00:14 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Otherwise, write out in binary.
|
|
|
|
OS << "0b";
|
2011-06-23 17:09:15 +08:00
|
|
|
for (unsigned j = 8; j--;) {
|
2010-02-10 07:00:14 +08:00
|
|
|
unsigned Bit = (Code[i] >> j) & 1;
|
2011-03-27 09:44:40 +08:00
|
|
|
|
2010-11-15 13:56:19 +08:00
|
|
|
unsigned FixupBit;
|
2013-06-18 15:20:20 +08:00
|
|
|
if (MAI->isLittleEndian())
|
2010-11-15 13:56:19 +08:00
|
|
|
FixupBit = i * 8 + j;
|
|
|
|
else
|
|
|
|
FixupBit = i * 8 + (7-j);
|
2011-03-27 09:44:40 +08:00
|
|
|
|
2011-06-23 17:09:15 +08:00
|
|
|
if (uint8_t MapEntry = FixupMap[FixupBit]) {
|
|
|
|
assert(Bit == 0 && "Encoder wrote into fixed up bit!");
|
|
|
|
OS << char('A' + MapEntry - 1);
|
2010-02-10 07:00:14 +08:00
|
|
|
} else
|
|
|
|
OS << Bit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-02-04 20:51:26 +08:00
|
|
|
OS << "]\n";
|
2010-02-10 07:00:14 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
|
|
|
|
MCFixup &F = Fixups[i];
|
2018-04-27 23:45:54 +08:00
|
|
|
const MCFixupKindInfo &Info =
|
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant
expressions. This improves the handing of preprocessor expressions
that must be resolved at parse time. This idiom can be found as
assembling-time assertion checks in source-level assemblers. Note that
this relies on the MCStreamer to keep sufficient tabs on Section /
Fragment information which the MCAsmStreamer does not. As a result the
textual output may fail where the equivalent object generation would
pass. This can most easily be resolved by folding the MCAsmStreamer
and MCObjectStreamer together which is planned for in a separate
patch.
Currently, this feature is only enabled for assembly input, keeping IR
compilation consistent between assembly and object generation.
Reviewers: echristo, rnk, probinson, espindola, peter.smith
Reviewed By: peter.smith
Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D45164
llvm-svn: 331218
2018-05-01 03:22:40 +08:00
|
|
|
getAssembler().getBackend().getFixupKindInfo(F.getKind());
|
2010-02-10 07:00:14 +08:00
|
|
|
OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
|
2010-02-10 12:47:08 +08:00
|
|
|
<< ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
|
2010-02-10 07:00:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-14 13:58:16 +08:00
|
|
|
void MCAsmStreamer::emitInstruction(const MCInst &Inst,
|
2019-02-04 20:51:26 +08:00
|
|
|
const MCSubtargetInfo &STI) {
|
2016-10-14 13:47:37 +08:00
|
|
|
assert(getCurrentSectionOnly() &&
|
2013-04-18 05:18:16 +08:00
|
|
|
"Cannot emit contents before setting section!");
|
2010-02-10 07:00:14 +08:00
|
|
|
|
|
|
|
// Show the encoding in a comment if we have a code emitter.
|
2019-02-04 20:51:26 +08:00
|
|
|
AddEncodingComment(Inst, STI);
|
2010-02-10 07:00:14 +08:00
|
|
|
|
2010-02-09 08:54:51 +08:00
|
|
|
// Show the MCInst if enabled.
|
2010-05-26 23:18:13 +08:00
|
|
|
if (ShowInst) {
|
2015-02-05 08:58:51 +08:00
|
|
|
Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
|
2010-05-26 23:18:13 +08:00
|
|
|
GetCommentOS() << "\n";
|
|
|
|
}
|
|
|
|
|
2015-06-19 04:43:22 +08:00
|
|
|
if(getTargetStreamer())
|
2020-01-04 02:55:30 +08:00
|
|
|
getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
|
2015-06-19 04:43:22 +08:00
|
|
|
else
|
2020-01-04 02:55:30 +08:00
|
|
|
InstPrinter->printInst(&Inst, 0, "", STI, OS);
|
2015-05-27 20:13:06 +08:00
|
|
|
|
2017-04-14 15:44:23 +08:00
|
|
|
StringRef Comments = CommentToEmit;
|
|
|
|
if (Comments.size() && Comments.back() != '\n')
|
|
|
|
GetCommentOS() << "\n";
|
|
|
|
|
2010-01-22 15:36:39 +08:00
|
|
|
EmitEOL();
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitBundleAlignMode(unsigned AlignPow2) {
|
2012-12-21 03:05:53 +08:00
|
|
|
OS << "\t.bundle_align_mode " << AlignPow2;
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
|
2012-12-21 03:05:53 +08:00
|
|
|
OS << "\t.bundle_lock";
|
2013-01-08 05:51:08 +08:00
|
|
|
if (AlignToEnd)
|
|
|
|
OS << " align_to_end";
|
2012-12-21 03:05:53 +08:00
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitBundleUnlock() {
|
2012-12-21 03:05:53 +08:00
|
|
|
OS << "\t.bundle_unlock";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-07-15 04:44:00 +08:00
|
|
|
Optional<std::pair<bool, std::string>>
|
|
|
|
MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
|
|
|
|
const MCExpr *Expr, SMLoc,
|
|
|
|
const MCSubtargetInfo &STI) {
|
2015-11-12 21:33:00 +08:00
|
|
|
OS << "\t.reloc ";
|
|
|
|
Offset.print(OS, MAI);
|
|
|
|
OS << ", " << Name;
|
|
|
|
if (Expr) {
|
|
|
|
OS << ", ";
|
|
|
|
Expr->print(OS, MAI);
|
|
|
|
}
|
|
|
|
EmitEOL();
|
2020-07-15 04:44:00 +08:00
|
|
|
return None;
|
2015-11-12 21:33:00 +08:00
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitAddrsig() {
|
2018-07-18 06:17:18 +08:00
|
|
|
OS << "\t.addrsig";
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
|
2018-07-18 06:17:18 +08:00
|
|
|
OS << "\t.addrsig_sym ";
|
|
|
|
Sym->print(OS, MAI);
|
|
|
|
EmitEOL();
|
|
|
|
}
|
|
|
|
|
2010-09-23 02:18:30 +08:00
|
|
|
/// EmitRawText - If this file is backed by an assembly streamer, this dumps
|
2010-04-04 05:35:55 +08:00
|
|
|
/// the specified string in the output .s file. This capability is
|
|
|
|
/// indicated by the hasRawTextSupport() predicate.
|
2020-02-16 00:52:56 +08:00
|
|
|
void MCAsmStreamer::emitRawTextImpl(StringRef String) {
|
2010-04-04 06:06:56 +08:00
|
|
|
if (!String.empty() && String.back() == '\n')
|
|
|
|
String = String.substr(0, String.size()-1);
|
2010-04-04 05:35:55 +08:00
|
|
|
OS << String;
|
2010-04-04 06:06:56 +08:00
|
|
|
EmitEOL();
|
2010-04-04 05:35:55 +08:00
|
|
|
}
|
|
|
|
|
2020-04-21 10:28:13 +08:00
|
|
|
void MCAsmStreamer::finishImpl() {
|
2011-12-10 02:09:40 +08:00
|
|
|
// If we are generating dwarf for assembly source files dump out the sections.
|
|
|
|
if (getContext().getGenDwarfForAssembly())
|
2014-04-01 15:35:52 +08:00
|
|
|
MCGenDwarfInfo::Emit(this);
|
|
|
|
|
|
|
|
// Emit the label for the line table, if requested - since the rest of the
|
|
|
|
// line table will be defined by .loc/.file directives, and not emitted
|
|
|
|
// directly, the label is the only work required here.
|
2019-04-11 02:30:03 +08:00
|
|
|
const auto &Tables = getContext().getMCDwarfLineTables();
|
2014-04-01 15:35:52 +08:00
|
|
|
if (!Tables.empty()) {
|
2014-04-01 16:07:52 +08:00
|
|
|
assert(Tables.size() == 1 && "asm output only supports one line table");
|
2014-04-01 15:35:52 +08:00
|
|
|
if (auto *Label = Tables.begin()->second.getLabel()) {
|
|
|
|
SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
|
2020-02-15 11:21:58 +08:00
|
|
|
emitLabel(Label);
|
2014-04-01 15:35:52 +08:00
|
|
|
}
|
|
|
|
}
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|
2013-09-10 03:48:37 +08:00
|
|
|
|
2010-01-22 15:29:22 +08:00
|
|
|
MCStreamer *llvm::createAsmStreamer(MCContext &Context,
|
2015-04-10 05:06:08 +08:00
|
|
|
std::unique_ptr<formatted_raw_ostream> OS,
|
2014-05-07 21:00:43 +08:00
|
|
|
bool isVerboseAsm, bool useDwarfDirectory,
|
2018-04-27 23:45:54 +08:00
|
|
|
MCInstPrinter *IP,
|
|
|
|
std::unique_ptr<MCCodeEmitter> &&CE,
|
|
|
|
std::unique_ptr<MCAsmBackend> &&MAB,
|
|
|
|
bool ShowInst) {
|
2015-04-10 05:06:08 +08:00
|
|
|
return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
|
2018-04-27 23:45:54 +08:00
|
|
|
useDwarfDirectory, IP, std::move(CE), std::move(MAB),
|
|
|
|
ShowInst);
|
2009-06-24 09:03:06 +08:00
|
|
|
}
|