Skip to content

Commit 75abeb6

Browse files
mhjacobsonbenshi001
authored andcommitted
[AVR] emit 'MCSA_Global' references to '__do_global_ctors' and '__do_global_dtors'
Emit references to '__do_global_ctors' and '__do_global_dtors' to allow constructor/destructor routines to run. Reviewed by: MaskRay Differential Revision: https://reviews.llvm.org/D107133
1 parent ac7c7cb commit 75abeb6

File tree

4 files changed

+62
-25
lines changed

4 files changed

+62
-25
lines changed

llvm/lib/Target/AVR/AVRAsmPrinter.cpp

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/CodeGen/TargetRegisterInfo.h"
2525
#include "llvm/CodeGen/TargetSubtargetInfo.h"
2626
#include "llvm/IR/Mangler.h"
27+
#include "llvm/MC/MCContext.h"
2728
#include "llvm/MC/MCInst.h"
2829
#include "llvm/MC/MCStreamer.h"
2930
#include "llvm/MC/MCSymbol.h"
@@ -38,9 +39,8 @@ namespace llvm {
3839
/// An AVR assembly code printer.
3940
class AVRAsmPrinter : public AsmPrinter {
4041
public:
41-
AVRAsmPrinter(TargetMachine &TM,
42-
std::unique_ptr<MCStreamer> Streamer)
43-
: AsmPrinter(TM, std::move(Streamer)), MRI(*TM.getMCRegisterInfo()) { }
42+
AVRAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
43+
: AsmPrinter(TM, std::move(Streamer)), MRI(*TM.getMCRegisterInfo()) {}
4444

4545
StringRef getPassName() const override { return "AVR Assembly Printer"; }
4646

@@ -56,8 +56,13 @@ class AVRAsmPrinter : public AsmPrinter {
5656

5757
const MCExpr *lowerConstant(const Constant *CV) override;
5858

59+
void emitXXStructor(const DataLayout &DL, const Constant *CV) override;
60+
61+
bool doFinalization(Module &M) override;
62+
5963
private:
6064
const MCRegisterInfo &MRI;
65+
bool EmittedStructorSymbolAttrs = false;
6166
};
6267

6368
void AVRAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
@@ -193,9 +198,47 @@ const MCExpr *AVRAsmPrinter::lowerConstant(const Constant *CV) {
193198
return AsmPrinter::lowerConstant(CV);
194199
}
195200

201+
void AVRAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) {
202+
if (!EmittedStructorSymbolAttrs) {
203+
OutStreamer->emitRawComment(
204+
" Emitting these undefined symbol references causes us to link the"
205+
" libgcc code that runs our constructors/destructors");
206+
OutStreamer->emitRawComment(" This matches GCC's behavior");
207+
208+
MCSymbol *CtorsSym = OutContext.getOrCreateSymbol("__do_global_ctors");
209+
OutStreamer->emitSymbolAttribute(CtorsSym, MCSA_Global);
210+
211+
MCSymbol *DtorsSym = OutContext.getOrCreateSymbol("__do_global_dtors");
212+
OutStreamer->emitSymbolAttribute(DtorsSym, MCSA_Global);
213+
214+
EmittedStructorSymbolAttrs = true;
215+
}
216+
217+
AsmPrinter::emitXXStructor(DL, CV);
218+
}
219+
220+
bool AVRAsmPrinter::doFinalization(Module &M) {
221+
MCSymbol *DoCopyData = OutContext.getOrCreateSymbol("__do_copy_data");
222+
MCSymbol *DoClearBss = OutContext.getOrCreateSymbol("__do_clear_bss");
223+
224+
// FIXME: We can disable __do_copy_data if there are no static RAM variables.
225+
226+
OutStreamer->emitRawComment(
227+
" Declaring this symbol tells the CRT that it should");
228+
OutStreamer->emitRawComment(
229+
"copy all variables from program memory to RAM on startup");
230+
OutStreamer->emitSymbolAttribute(DoCopyData, MCSA_Global);
231+
232+
OutStreamer->emitRawComment(
233+
" Declaring this symbol tells the CRT that it should");
234+
OutStreamer->emitRawComment("clear the zeroed data section on startup");
235+
OutStreamer->emitSymbolAttribute(DoClearBss, MCSA_Global);
236+
237+
return AsmPrinter::doFinalization(M);
238+
}
239+
196240
} // end of namespace llvm
197241

198242
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAVRAsmPrinter() {
199243
llvm::RegisterAsmPrinter<llvm::AVRAsmPrinter> X(llvm::getTheAVRTarget());
200244
}
201-

llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,4 @@ AVRTargetStreamer::AVRTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
2121
AVRTargetAsmStreamer::AVRTargetAsmStreamer(MCStreamer &S)
2222
: AVRTargetStreamer(S) {}
2323

24-
void AVRTargetStreamer::finish() {
25-
MCStreamer &OS = getStreamer();
26-
MCContext &Context = OS.getContext();
27-
28-
MCSymbol *DoCopyData = Context.getOrCreateSymbol("__do_copy_data");
29-
MCSymbol *DoClearBss = Context.getOrCreateSymbol("__do_clear_bss");
30-
31-
// FIXME: We can disable __do_copy_data if there are no static RAM variables.
32-
33-
OS.emitRawComment(" Declaring this symbol tells the CRT that it should");
34-
OS.emitRawComment("copy all variables from program memory to RAM on startup");
35-
OS.emitSymbolAttribute(DoCopyData, MCSA_Global);
36-
37-
OS.emitRawComment(" Declaring this symbol tells the CRT that it should");
38-
OS.emitRawComment("clear the zeroed data section on startup");
39-
OS.emitSymbolAttribute(DoClearBss, MCSA_Global);
40-
}
41-
4224
} // end namespace llvm
43-

llvm/lib/Target/AVR/MCTargetDesc/AVRTargetStreamer.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ class MCStreamer;
1818
class AVRTargetStreamer : public MCTargetStreamer {
1919
public:
2020
explicit AVRTargetStreamer(MCStreamer &S);
21-
22-
void finish() override;
2321
};
2422

2523
/// A target streamer for textual AVR assembly code.

llvm/test/CodeGen/AVR/ctors.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -march=avr | FileCheck %s
3+
4+
define void @do_nothing() addrspace(1) #0 {
5+
; CHECK-LABEL: do_nothing:
6+
; CHECK: ; %bb.0:
7+
; CHECK-NEXT: ret
8+
ret void
9+
}
10+
11+
; CHECK: .globl __do_global_ctors
12+
@llvm.global_ctors = appending global [1 x { i32, void () addrspace(1)*, i8* }] [{ i32, void () addrspace(1)*, i8* } { i32 65535, void () addrspace(1)* @do_nothing, i8* null }]
13+
14+
; CHECK: .globl __do_global_dtors
15+
@llvm.global_dtors = appending global [1 x { i32, void () addrspace(1)*, i8* }] [{ i32, void () addrspace(1)*, i8* } { i32 65535, void () addrspace(1)* @do_nothing, i8* null }]

0 commit comments

Comments
 (0)