blob: fa999292fbd37f20e4120a3c1454100d6bcad242 [file] [log] [blame]
//===- lld/Core/Alias.h - Alias atoms -------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Provide alias atoms.
///
//===----------------------------------------------------------------------===//
#ifndef LLD_CORE_ALIAS_H
#define LLD_CORE_ALIAS_H
#include "lld/Core/LLVM.h"
#include "lld/Core/Simple.h"
#include "llvm/ADT/Optional.h"
#include <string>
namespace lld {
// An AliasAtom is a zero-size atom representing an alias for other atom. It has
// a LayoutAfter reference to the target atom, so that this atom and the target
// atom will be laid out at the same location in the final result. Initially
// the target atom is an undefined atom. Resolver will replace it with a defined
// one.
//
// It does not have attributes itself. Most member function calls are forwarded
// to the target atom.
class AliasAtom : public SimpleDefinedAtom {
public:
AliasAtom(const File &file, StringRef name)
: SimpleDefinedAtom(file), _name(name) {}
StringRef name() const override { return _name; }
uint64_t size() const override { return 0; }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
Scope scope() const override {
getTarget();
return _target ? _target->scope() : scopeLinkageUnit;
}
Merge merge() const override {
if (_merge.hasValue())
return _merge.getValue();
getTarget();
return _target ? _target->merge() : mergeNo;
}
void setMerge(Merge val) { _merge = val; }
ContentType contentType() const override {
getTarget();
return _target ? _target->contentType() : typeUnknown;
}
Interposable interposable() const override {
getTarget();
return _target ? _target->interposable() : interposeNo;
}
SectionChoice sectionChoice() const override {
getTarget();
return _target ? _target->sectionChoice() : sectionBasedOnContent;
}
StringRef customSectionName() const override {
getTarget();
return _target ? _target->customSectionName() : StringRef("");
}
DeadStripKind deadStrip() const override { return _deadStrip; }
void setDeadStrip(DeadStripKind val) { _deadStrip = val; }
private:
void getTarget() const {
if (_target)
return;
for (const Reference *r : *this) {
if (r->kindNamespace() == lld::Reference::KindNamespace::all &&
r->kindValue() == lld::Reference::kindLayoutAfter) {
_target = dyn_cast<DefinedAtom>(r->target());
return;
}
}
}
std::string _name;
mutable const DefinedAtom *_target = nullptr;
llvm::Optional<Merge> _merge = DefinedAtom::mergeNo;
DeadStripKind _deadStrip = DefinedAtom::deadStripNormal;
};
} // end namespace lld
#endif