Commit af0c406d authored by wolfgang's avatar wolfgang
Browse files

[project @ 2005-06-09 05:55:40 by wolfgang]

Registerised support for Darwin/x86, both NCG and mangled.

*) -fPIC doesn't work yet with -fvia-C.
*) Apple officially requires the stack to be 16-byte-aligned,
   GHC ignores this for now.
parent 246abe64
......@@ -509,12 +509,17 @@ bit or 64 bit precision.
-- Other things.
| CLTD MachRep -- sign extend %eax into %edx:%eax
| FETCHGOT Reg -- pseudo-insn for position-independent code
| FETCHGOT Reg -- pseudo-insn for ELF position-independent code
-- pretty-prints as
-- call 1f
-- 1: popl %reg
-- addl __GLOBAL_OFFSET_TABLE__+.-1b, %reg
| FETCHPC Reg -- pseudo-insn for Darwin position-independent code
-- pretty-prints as
-- call 1f
-- 1: popl %reg
data Operand
= OpReg Reg -- register
| OpImm Imm -- immediate value
......
......@@ -321,12 +321,29 @@ pprCLabel_asm l = asmSDoc (pprCLabel l)
needImportedSymbols = True
-- We don't need to declare any offset tables
-- We don't need to declare any offset tables.
-- However, for PIC on x86, we need a small helper function.
#if i386_TARGET_ARCH
pprGotDeclaration
| opt_PIC
= vcat [
ptext SLIT(".section __TEXT,__textcoal_nt,coalesced,no_toc"),
ptext SLIT(".weak_definition ___i686.get_pc_thunk.ax"),
ptext SLIT(".private_extern ___i686.get_pc_thunk.ax"),
ptext SLIT("___i686.get_pc_thunk.ax:"),
ptext SLIT("\tmovl (%esp), %eax"),
ptext SLIT("\tret")
]
| otherwise = Pretty.empty
#else
pprGotDeclaration = Pretty.empty
#endif
-- On Darwin, we have to generate our own stub code for lazy binding..
-- There are two versions, one for PIC and one for non-PIC.
-- For each processor architecture, there are two versions, one for PIC
-- and one for non-PIC.
pprImportedSymbol importedLbl
#if powerpc_TARGET_ARCH
| Just (CodeStub, lbl) <- dynamicLinkerLabelInfo importedLbl
= case opt_PIC of
False ->
......@@ -369,7 +386,49 @@ pprImportedSymbol importedLbl
ptext SLIT("\t.indirect_symbol") <+> pprCLabel_asm lbl,
ptext SLIT("\t.long dyld_stub_binding_helper")
]
#elif i386_TARGET_ARCH
| Just (CodeStub, lbl) <- dynamicLinkerLabelInfo importedLbl
= case opt_PIC of
False ->
vcat [
ptext SLIT(".symbol_stub"),
ptext SLIT("L") <> pprCLabel_asm lbl <> ptext SLIT("$stub:"),
ptext SLIT("\t.indirect_symbol") <+> pprCLabel_asm lbl,
ptext SLIT("\tjmp *L") <> pprCLabel_asm lbl
<> ptext SLIT("$lazy_ptr"),
ptext SLIT("L") <> pprCLabel_asm lbl
<> ptext SLIT("$stub_binder:"),
ptext SLIT("\tpushl $L") <> pprCLabel_asm lbl
<> ptext SLIT("$lazy_ptr"),
ptext SLIT("\tjmp dyld_stub_binding_helper")
]
True ->
vcat [
ptext SLIT(".section __TEXT,__picsymbolstub2,")
<> ptext SLIT("symbol_stubs,pure_instructions,25"),
ptext SLIT("L") <> pprCLabel_asm lbl <> ptext SLIT("$stub:"),
ptext SLIT("\t.indirect_symbol") <+> pprCLabel_asm lbl,
ptext SLIT("\tcall ___i686.get_pc_thunk.ax"),
ptext SLIT("1:"),
ptext SLIT("\tmovl L") <> pprCLabel_asm lbl
<> ptext SLIT("$lazy_ptr-1b(%eax),%edx"),
ptext SLIT("\tjmp %edx"),
ptext SLIT("L") <> pprCLabel_asm lbl
<> ptext SLIT("$stub_binder:"),
ptext SLIT("\tlea L") <> pprCLabel_asm lbl
<> ptext SLIT("$lazy_ptr-1b(%eax),%eax"),
ptext SLIT("\tpushl %eax"),
ptext SLIT("\tjmp dyld_stub_binding_helper")
]
$+$ vcat [ ptext SLIT(".section __DATA, __la_sym_ptr")
<> (if opt_PIC then int 2 else int 3)
<> ptext SLIT(",lazy_symbol_pointers"),
ptext SLIT("L") <> pprCLabel_asm lbl <> ptext SLIT("$lazy_ptr:"),
ptext SLIT("\t.indirect_symbol") <+> pprCLabel_asm lbl,
ptext SLIT("\t.long L") <> pprCLabel_asm lbl
<> ptext SLIT("$stub_binder")
]
#endif
-- We also have to declare our symbol pointers ourselves:
| Just (SymbolPtr, lbl) <- dynamicLinkerLabelInfo importedLbl
= vcat [
......@@ -475,9 +534,21 @@ pprImportedSymbol _ = empty
initializePicBase :: Reg -> [NatCmmTop] -> NatM [NatCmmTop]
#if powerpc_TARGET_ARCH && darwin_TARGET_OS
#if darwin_TARGET_OS
-- Darwin is simple: just fetch the address of a local label.
-- The FETCHPC pseudo-instruction is expanded to multiple instructions
-- during pretty-printing so that we don't have to deal with the
-- local label:
-- PowerPC version:
-- bcl 20,31,1f.
-- 1: mflr picReg
-- i386 version:
-- call 1f
-- 1: popl %picReg
initializePicBase picReg (CmmProc info lab params blocks : statics)
= return (CmmProc info lab params (b':tail blocks) : statics)
where BasicBlock bID insns = head blocks
......@@ -531,9 +602,4 @@ initializePicBase picReg (CmmProc info lab params blocks : statics)
initializePicBase picReg proc = panic "initializePicBase"
-- mingw32_TARGET_OS: not needed, won't be called
-- i386_TARGET_ARCH && darwin_TARGET_OS:
-- (just for completeness ;-)
-- call 1f
-- 1: popl %picReg
#endif
......@@ -617,7 +617,9 @@ pprSectionHeader Text
= ptext
IF_ARCH_alpha(SLIT("\t.text\n\t.align 3") {-word boundary-}
,IF_ARCH_sparc(SLIT(".text\n\t.align 4") {-word boundary-}
,IF_ARCH_i386(SLIT(".text\n\t.align 4,0x90") {-needs per-OS variation!-}
,IF_ARCH_i386(IF_OS_darwin(SLIT(".text\n\t.align 2"),
SLIT(".text\n\t.align 4,0x90"))
{-needs per-OS variation!-}
,IF_ARCH_x86_64(SLIT(".text\n\t.align 8") {-needs per-OS variation!-}
,IF_ARCH_powerpc(SLIT(".text\n.align 2")
,)))))
......@@ -625,7 +627,8 @@ pprSectionHeader Data
= ptext
IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
,IF_ARCH_i386(SLIT(".data\n\t.align 4")
,IF_ARCH_i386(IF_OS_darwin(SLIT(".data\n\t.align 2"),
SLIT(".data\n\t.align 4"))
,IF_ARCH_x86_64(SLIT(".data\n\t.align 8")
,IF_ARCH_powerpc(SLIT(".data\n.align 2")
,)))))
......@@ -633,7 +636,8 @@ pprSectionHeader ReadOnlyData
= ptext
IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 4")
,IF_ARCH_i386(IF_OS_darwin(SLIT(".const\n.align 2"),
SLIT(".section .rodata\n\t.align 4"))
,IF_ARCH_x86_64(SLIT(".section .rodata\n\t.align 8")
,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const\n.align 2"),
SLIT(".section .rodata\n\t.align 2"))
......@@ -642,7 +646,8 @@ pprSectionHeader RelocatableReadOnlyData
= ptext
IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 4")
,IF_ARCH_i386(IF_OS_darwin(SLIT(".const_data\n.align 2"),
SLIT(".section .rodata\n\t.align 4"))
,IF_ARCH_x86_64(SLIT(".section .rodata\n\t.align 8")
,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const_data\n.align 2"),
SLIT(".data\n\t.align 2"))
......@@ -651,7 +656,8 @@ pprSectionHeader UninitialisedData
= ptext
IF_ARCH_alpha(SLIT("\t.bss\n\t.align 3")
,IF_ARCH_sparc(SLIT(".bss\n\t.align 8") {-<8 will break double constants -}
,IF_ARCH_i386(SLIT(".section .bss\n\t.align 4")
,IF_ARCH_i386(IF_OS_darwin(SLIT(".const_data\n\t.align 2"),
SLIT(".section .bss\n\t.align 4"))
,IF_ARCH_x86_64(SLIT(".section .bss\n\t.align 8")
,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const_data\n.align 2"),
SLIT(".section .bss\n\t.align 2"))
......@@ -660,7 +666,8 @@ pprSectionHeader ReadOnlyData16
= ptext
IF_ARCH_alpha(SLIT("\t.data\n\t.align 4")
,IF_ARCH_sparc(SLIT(".data\n\t.align 16")
,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 16")
,IF_ARCH_i386(IF_OS_darwin(SLIT(".const\n.align 4"),
SLIT(".section .rodata\n\t.align 16"))
,IF_ARCH_x86_64(SLIT(".section .rodata.cst16\n\t.align 16")
,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const\n.align 4"),
SLIT(".section .rodata\n\t.align 4"))
......@@ -701,7 +708,7 @@ pprASCII str
pprAlign bytes =
IF_ARCH_alpha(ptextSLIT(".align ") <> int pow2,
IF_ARCH_i386(ptext SLIT(".align ") <> int bytes,
IF_ARCH_i386(ptext SLIT(".align ") <> int IF_OS_darwin(pow2,bytes),
IF_ARCH_x86_64(ptext SLIT(".align ") <> int bytes,
IF_ARCH_sparc(ptext SLIT(".align ") <> int bytes,
IF_ARCH_powerpc(ptext SLIT(".align ") <> int pow2,)))))
......@@ -1303,6 +1310,7 @@ pprInstr (CVTSI2SS from to) = pprOpReg SLIT("cvtsi2ss") from to
pprInstr (CVTSI2SD from to) = pprOpReg SLIT("cvtsi2sd") from to
#endif
-- FETCHGOT for PIC on ELF platforms
pprInstr (FETCHGOT reg)
= vcat [ ptext SLIT("\tcall 1f"),
hcat [ ptext SLIT("1:\tpopl\t"), pprReg I32 reg ],
......@@ -1310,6 +1318,17 @@ pprInstr (FETCHGOT reg)
pprReg I32 reg ]
]
-- FETCHPC for PIC on Darwin/x86
-- get the instruction pointer into a register
-- (Terminology note: the IP is called Program Counter on PPC,
-- and it's a good thing to use the same name on both platforms)
pprInstr (FETCHPC reg)
= vcat [ ptext SLIT("\tcall 1f"),
hcat [ ptext SLIT("1:\tpopl\t"), pprReg I32 reg ]
]
#endif
-- -----------------------------------------------------------------------------
......
......@@ -215,6 +215,7 @@ regUsage instr = case instr of
#endif
FETCHGOT reg -> mkRU [] [reg]
FETCHPC reg -> mkRU [] [reg]
COMMENT _ -> noUsage
DELTA _ -> noUsage
......@@ -539,7 +540,8 @@ patchRegs instr env = case instr of
CALL (Right reg) p -> CALL (Right (env reg)) p
FETCHGOT reg -> FETCHGOT (env reg)
FETCHPC reg -> FETCHPC (env reg)
NOP -> instr
COMMENT _ -> instr
DELTA _ -> instr
......
......@@ -290,7 +290,7 @@ sub init_TARGET_STUFF {
$T_HDR_vector = "\t\.text\n\t\.align 2\n";
#--------------------------------------------------------#
} elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ ) {
} elsif ( $TargetPlatform =~ /^powerpc-apple-darwin.*/ ) {
# Apple PowerPC Darwin/MacOS X.
$T_STABBY = 0; # 1 iff .stab things (usually if a.out format)
$T_US = '_'; # _ if symbols have an underscore on the front
......@@ -314,6 +314,34 @@ sub init_TARGET_STUFF {
$T_HDR_entry = "\t\.text\n\t\.align 2\n";
$T_HDR_vector = "\t\.text\n\t\.align 2\n";
#--------------------------------------------------------#
} elsif ( $TargetPlatform =~ /^i386-apple-darwin.*/ ) {
# Apple PowerPC Darwin/MacOS X.
$T_STABBY = 0; # 1 iff .stab things (usually if a.out format)
$T_US = '_'; # _ if symbols have an underscore on the front
$T_PRE_APP = 'DOESNT APPLY'; # regexp that says what comes before APP/NO_APP
$T_CONST_LBL = '^\LC\d+:'; # regexp for what such a lbl looks like
$T_POST_LBL = ':';
$T_X86_PRE_LLBL_PAT = 'L';
$T_X86_PRE_LLBL = 'L';
$T_X86_BADJMP = '^\tjmp [^L\*]';
$T_MOVE_DIRVS = '^(\s*(\.align \d+|\.text|\.data|\.const_data|\.cstring|\.non_lazy_symbol_pointer|\.const|\.static_const|\.literal4|\.literal8|\.static_data|\.globl \S+|\.section .*|\.lcomm.*)\n)';
$T_COPY_DIRVS = '\.(globl|lcomm)';
$T_DOT_WORD = '\.(long|short|byte|fill|space)';
$T_DOT_GLOBAL = '\.globl';
$T_HDR_toc = "\.toc\n";
$T_HDR_literal = "\t\.const\n\t\.align 2\n";
$T_HDR_misc = "\t\.text\n\t\.align 2\n";
$T_HDR_data = "\t\.data\n\t\.align 2\n";
$T_HDR_rodata = "\t\.const\n\t\.align 2\n";
$T_HDR_relrodata= "\t\.const_data\n\t\.align 2\n";
$T_HDR_closure = "\t\.data\n\t\.align 2\n";
$T_HDR_info = "\t\.text\n\t\.align 2\n";
$T_HDR_entry = "\t\.text\n\t\.align 2\n";
$T_HDR_vector = "\t\.text\n\t\.align 2\n";
#--------------------------------------------------------#
} elsif ( $TargetPlatform =~ /^powerpc-.*-linux/ ) {
# PowerPC Linux
......@@ -551,13 +579,13 @@ sub mangle_asm {
# The .no_dead_strip directives are actually put there by
# the gcc3 "used" attribute on entry points.
} elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ && (
} elsif ( $TargetPlatform =~ /^.*-apple-darwin.*/ && (
/^\s*\.picsymbol_stub/
|| /^\s*\.section __TEXT,__picsymbol_stub1,.*/
|| /^\s*\.section __TEXT,__picsymbolstub1,.*/
|| /^\s*\.section __TEXT,__picsymbol_stub\d,.*/
|| /^\s*\.section __TEXT,__picsymbolstub\d,.*/
|| /^\s*\.symbol_stub/
|| /^\s*\.section __TEXT,__symbol_stub1,.*/
|| /^\s*\.section __TEXT,__symbolstub1,.*/
|| /^\s*\.section __TEXT,__symbol_stub\d,.*/
|| /^\s*\.section __TEXT,__symbolstub\d,.*/
|| /^\s*\.lazy_symbol_pointer/
|| /^\s*\.non_lazy_symbol_pointer/ ))
{
......@@ -565,7 +593,7 @@ sub mangle_asm {
$chkcat[$i] = 'dyld';
$chksymb[$i] = '';
} elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ && $chkcat[$i] eq 'dyld' && /^\s*\.data/)
} elsif ( $TargetPlatform =~ /^.*-apple-darwin.*/ && $chkcat[$i] eq 'dyld' && /^\s*\.data/)
{ # non_lazy_symbol_ptrs that point to local symbols
$chk[++$i] = $_;
$chkcat[$i] = 'dyld';
......@@ -683,6 +711,15 @@ sub mangle_asm {
$chkcat[$i] = 'misc';
$chksymb[$i] = $1;
} elsif ( $TargetPlatform =~ /^i386-apple-darwin/ && /^(___i686\.get_pc_thunk\.[abcd]x):/o) {
# To handle PIC on Darwin/x86, we need to appropriately pass through
# the get_pc_thunk functions. The need to be put into a special section
# marked as coalesced (otherwise the .weak_definition doesn't work
# on Darwin).
$chk[++$i] = $_;
$chkcat[$i] = 'get_pc_thunk';
$chksymb[$i] = $1;
} elsif ( /^${T_US}[A-Za-z0-9_]/o
&& ( $TargetPlatform !~ /^hppa/ # need to avoid local labels in this case
|| ! /^L\$\d+$/ )
......@@ -801,6 +838,20 @@ sub mangle_asm {
$r = $& . $r;
}
if ($TargetPlatform =~ /^i386-apple-darwin/) {
$pcrel_label = $p;
$pcrel_label =~ s/(.|\n)*^(\"?L\d+\$pb\"?):\n(.|\n)*/$2/ or $pcrel_label = "";
$pcrel_reg = $p;
$pcrel_reg =~ s/(.|\n)*.*___i686\.get_pc_thunk\.([abcd]x)\n(.|\n)*/$2/ or $pcrel_reg = "";
$p =~ s/^\s+call\s+___i686\.get_pc_thunk\..x//;
$p =~ s/^\"?L\d+\$pb\"?:\n//;
if ($pcrel_reg eq "bx") {
# Bad gcc. Goes and uses %ebx, our BaseReg, for PIC. Bad gcc.
die "Darwin/x86: -fPIC -via-C doesn't work yet, use -fasm. Aborting."
}
}
} elsif ($TargetPlatform =~ /^x86_64-/) {
$p =~ s/^\tpushq\s+\%r(bx|bp|12|13|14)\n//g;
$p =~ s/^\tmovq\s+\%r(bx|bp|12|13|14),\s*\d*\(\%rsp\)\n//g;
......@@ -843,7 +894,7 @@ sub mangle_asm {
$p =~ s/^\tsw\t\$fp,\d+\(\$sp\)\n//;
$p =~ s/^\tsw\t\$28,\d+\(\$sp\)\n//;
$p =~ s/__FRAME__/$FRAME/;
} elsif ($TargetPlatform =~ /^powerpc-apple-.*/) {
} elsif ($TargetPlatform =~ /^powerpc-apple-darwin.*/) {
$pcrel_label = $p;
$pcrel_label =~ s/(.|\n)*^(\"?L\d+\$pb\"?):\n(.|\n)*/$2/ or $pcrel_label = "";
......@@ -921,7 +972,7 @@ sub mangle_asm {
die "Prologue junk?: $p\n" if $p =~ /^\s+[^\s\.]/;
# For PIC, we want to keep part of the prologue
if ($TargetPlatform =~ /^powerpc-apple-.*/ && $pcrel_label ne "") {
if ($TargetPlatform =~ /^powerpc-apple-darwin.*/ && $pcrel_label ne "") {
# Darwin: load the current instruction pointer into register r31
$p .= "bcl 20,31,$pcrel_label\n";
$p .= "$pcrel_label:\n";
......@@ -933,6 +984,9 @@ sub mangle_asm {
$p .= "\tmflr 30\n";
$p .= "\tlwz 0,.LCL$pcrel_label-.LCF$pcrel_label(30)\n";
$p .= "\tadd 30,0,30\n";
} elsif ($TargetPlatform =~ /^i386-apple-darwin.*/ && $pcrel_label ne "") {
$p .= "\tcall ___i686.get_pc_thunk.$pcrel_reg\n";
$p .= "$pcrel_label:\n";
}
# glue together what's left
......@@ -972,7 +1026,7 @@ sub mangle_asm {
$e =~ s/^\tlw\t\$fp,\d+\(\$sp\)\n//;
$e =~ s/^\taddu\t\$sp,\$sp,\d+\n//;
$e =~ s/^\tj\t\$31\n//;
} elsif ($TargetPlatform =~ /^powerpc-apple-.*/) {
} elsif ($TargetPlatform =~ /^powerpc-apple-darwin.*/) {
$e =~ s/^\taddi r1,r1,\d+\n//;
$e =~ s/^\tlwz r\d+,\d+\(r1\)\n//;
$e =~ s/^\tlmw r\d+,-\d+\(r1\)\n//;
......@@ -1023,9 +1077,10 @@ sub mangle_asm {
# toss all calls to __DISCARD__
$c =~ s/^\t(call|jbsr|jal)\s+${T_US}__DISCARD__\n//go;
$c =~ s/^\tjsr\s+\$26\s*,\s*${T_US}__DISCARD__\n//go if $TargetPlatform =~ /^alpha-/;
$c =~ s/^\tbl\s+L___DISCARD__\$stub\n//go if $TargetPlatform =~ /^powerpc-apple-.*/;
$c =~ s/^\tbl\s+L___DISCARD__\$stub\n//go if $TargetPlatform =~ /^powerpc-apple-darwin.*/;
$c =~ s/^\tbl\s+__DISCARD__(\@plt)?\n//go if $TargetPlatform =~ /^powerpc-.*-linux/;
$c =~ s/^\tbl\s+\.__DISCARD__\n\s+nop\n//go if $TargetPlatform =~ /^powerpc64-.*-linux/;
$c =~ s/^\tcall\s+L___DISCARD__\$stub\n//go if $TargetPlatform =~ /i386-apple-darwin.*/;
# IA64: mangle tailcalls into jumps here
if ($TargetPlatform =~ /^ia64-/) {
......@@ -1321,12 +1376,16 @@ sub mangle_asm {
$j++;
}
} elsif ( $TargetPlatform =~ /^powerpc-apple-.*/ && $chkcat[$i] eq 'dyld' ) {
# powerpc-apple: dynamic linker stubs
} elsif ( $TargetPlatform =~ /^.*-apple-darwin.*/ && $chkcat[$i] eq 'dyld' ) {
# apple-darwin: dynamic linker stubs
if($chk[$i] !~ /\.indirect_symbol ___DISCARD__/)
{ # print them out unchanged, but remove the stubs for __DISCARD__
print OUTASM $chk[$i];
}
} elsif ( $TargetPlatform =~ /^i386-apple-darwin.*/ && $chkcat[$i] eq 'get_pc_thunk' ) {
# i386-apple-darwin: __i686.get_pc_thunk.[abcd]x
print OUTASM ".section __TEXT,__textcoal_nt,coalesced,no_toc\n";
print OUTASM $chk[$i];
} else {
&tidy_up_and_die(1,"$Pgm: unknown chkcat (ghc-asm: $TargetPlatform)\n$chkcat[$i]\n$chk[$i]\n");
}
......
......@@ -114,6 +114,12 @@ StgFunPtr StgReturn(void)
#ifdef i386_HOST_ARCH
#ifdef darwin_TARGET_OS
#define STG_GLOBAL ".globl "
#else
#define STG_GLOBAL ".global "
#endif
StgThreadReturnCode
StgRun(StgFunPtr f, StgRegTable *basereg) {
......@@ -140,7 +146,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
"movl %2,%%eax\n\t"
"jmp *%%eax\n\t"
".global " STG_RETURN "\n"
STG_GLOBAL STG_RETURN "\n"
STG_RETURN ":\n\t"
"movl %%esi, %%eax\n\t" /* Return value in R1 */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment