mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
add ability to call helper functions (#21275)
This commit is contained in:
parent
6208d4da8d
commit
4c2d438f75
3 changed files with 150 additions and 3 deletions
|
@ -1314,6 +1314,146 @@ void fixresult(ref CodeBuilder cdb, elem* e, regm_t retregs, ref regm_t outretre
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
* Extra information about each CLIB_A runtime library function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private
|
||||||
|
enum CLIB_A
|
||||||
|
{
|
||||||
|
realToDouble,
|
||||||
|
doubleToReal,
|
||||||
|
}
|
||||||
|
|
||||||
|
private
|
||||||
|
struct ClibInfo
|
||||||
|
{
|
||||||
|
regm_t retregs; // registers that 32 bit result is returned in
|
||||||
|
}
|
||||||
|
|
||||||
|
__gshared int clib_inited = false; // true if initialized
|
||||||
|
|
||||||
|
@trusted private
|
||||||
|
Symbol* symboly(string name, regm_t desregs)
|
||||||
|
{
|
||||||
|
Symbol* s = symbol_calloc(name);
|
||||||
|
s.Stype = tsclib;
|
||||||
|
s.Sclass = SC.extern_;
|
||||||
|
s.Sfl = FL.func;
|
||||||
|
s.Ssymnum = 0;
|
||||||
|
s.Sregsaved = fregsaved; // assume C conventions
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
private
|
||||||
|
void initClibInfo(ref Symbol*[CLIB_A.max + 1] clibsyms, ref ClibInfo[CLIB_A.max + 1] clibinfo)
|
||||||
|
{
|
||||||
|
foreach (s; clibsyms[])
|
||||||
|
{
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
s.Sxtrnnum = 0;
|
||||||
|
s.Stypidx = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private
|
||||||
|
void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t objfmt, exefmt_t exe)
|
||||||
|
{
|
||||||
|
switch (clib)
|
||||||
|
{
|
||||||
|
case CLIB_A.realToDouble:
|
||||||
|
{
|
||||||
|
string name = "__trunctfdf2";
|
||||||
|
s = symboly(name, mask(32));
|
||||||
|
cinfo.retregs = mask(32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CLIB_A.doubleToReal:
|
||||||
|
{
|
||||||
|
string name = "__extenddftf2";
|
||||||
|
s = symboly(name, mask(32));
|
||||||
|
cinfo.retregs = mask(32);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@trusted private
|
||||||
|
void getClibInfo(uint clib, Symbol** ps, ClibInfo** pinfo, objfmt_t objfmt, exefmt_t exe)
|
||||||
|
{
|
||||||
|
static Symbol*[CLIB_A.max + 1] clibsyms;
|
||||||
|
static ClibInfo[CLIB_A.max + 1] clibinfo;
|
||||||
|
|
||||||
|
if (!clib_inited)
|
||||||
|
{
|
||||||
|
initClibInfo(clibsyms, clibinfo);
|
||||||
|
clib_inited = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClibInfo* cinfo = &clibinfo[clib];
|
||||||
|
Symbol* s = clibsyms[clib];
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
getClibFunction(clib, s, cinfo, objfmt, exe);
|
||||||
|
clibsyms[clib] = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ps = s;
|
||||||
|
*pinfo = cinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Generate code sequence to call C runtime library support routine.
|
||||||
|
* clib = CLIB_A.xxxx
|
||||||
|
* keepmask = mask of registers not to destroy. Currently can
|
||||||
|
* handle only 1. Should use a temporary rather than
|
||||||
|
* push/pop for speed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@trusted
|
||||||
|
void callclib(ref CodeBuilder cdb, elem* e, uint clib, ref regm_t pretregs, regm_t keepmask)
|
||||||
|
{
|
||||||
|
//printf("callclib(e = %p, clib = %d, pretregs = %s, keepmask = %s\n", e, clib, regm_str(pretregs), regm_str(keepmask));
|
||||||
|
//elem_print(e);
|
||||||
|
|
||||||
|
Symbol* s;
|
||||||
|
ClibInfo* cinfo;
|
||||||
|
getClibInfo(clib, &s, &cinfo, config.objfmt, config.exe);
|
||||||
|
|
||||||
|
getregs(cdb,(~s.Sregsaved & (cgstate.allregs | INSTR.FLOATREGS | mask(cgstate.BP)) & ~keepmask)); // mask of regs destroyed
|
||||||
|
keepmask &= ~s.Sregsaved;
|
||||||
|
int npushed = popcnt(keepmask);
|
||||||
|
CodeBuilder cdbpop;
|
||||||
|
cdbpop.ctor();
|
||||||
|
gensaverestore(keepmask, cdb, cdbpop);
|
||||||
|
|
||||||
|
makeitextern(s);
|
||||||
|
int nalign = 0;
|
||||||
|
if (STACKALIGN >= 16)
|
||||||
|
{ // Align the stack (assume no args on stack)
|
||||||
|
int npush = npushed * REGSIZE + cgstate.stackpush;
|
||||||
|
if (npush & (STACKALIGN - 1))
|
||||||
|
{ nalign = STACKALIGN - (npush & (STACKALIGN - 1));
|
||||||
|
cod3_stackadj(cdb, nalign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cdb.gencs1(INSTR.branch_imm(1,0),0,FL.func,s); // CALL s
|
||||||
|
if (nalign)
|
||||||
|
cod3_stackadj(cdb, -nalign);
|
||||||
|
cgstate.calledafunc = 1;
|
||||||
|
|
||||||
|
cdb.append(cdbpop);
|
||||||
|
fixresult(cdb, e, cinfo.retregs, pretregs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************
|
/*******************************
|
||||||
* Generate code sequence for function call.
|
* Generate code sequence for function call.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -68,7 +68,7 @@ nothrow:
|
||||||
@trusted
|
@trusted
|
||||||
void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint idx)
|
void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint idx)
|
||||||
{
|
{
|
||||||
// TODO AArch64 floating point registers
|
assert(reg < 32); // TODO AArch64 floating point registers
|
||||||
if (!regsave.alignment)
|
if (!regsave.alignment)
|
||||||
regsave.alignment = REGSIZE;
|
regsave.alignment = REGSIZE;
|
||||||
idx = regsave.idx;
|
idx = regsave.idx;
|
||||||
|
@ -96,7 +96,7 @@ void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint
|
||||||
@trusted
|
@trusted
|
||||||
void REGSAVE_restore(const ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, uint idx)
|
void REGSAVE_restore(const ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, uint idx)
|
||||||
{
|
{
|
||||||
// TODO AArch64 floating point registers
|
assert(reg < 32); // TODO AArch64 floating point registers
|
||||||
// LDR reg,[BP, #idx]
|
// LDR reg,[BP, #idx]
|
||||||
code cs;
|
code cs;
|
||||||
cs.reg = reg;
|
cs.reg = reg;
|
||||||
|
|
|
@ -37,6 +37,7 @@ import dmd.backend.ty;
|
||||||
import dmd.backend.type;
|
import dmd.backend.type;
|
||||||
import dmd.backend.x86.xmm;
|
import dmd.backend.x86.xmm;
|
||||||
import dmd.backend.arm.cod1;
|
import dmd.backend.arm.cod1;
|
||||||
|
import dmd.backend.arm.instr : INSTR;
|
||||||
|
|
||||||
import dmd.backend.cg : segfl, stackfl;
|
import dmd.backend.cg : segfl, stackfl;
|
||||||
|
|
||||||
|
@ -349,7 +350,7 @@ uint gensaverestore(regm_t regm,ref CodeBuilder cdbsave,ref CodeBuilder cdbresto
|
||||||
|
|
||||||
if (cgstate.AArch64)
|
if (cgstate.AArch64)
|
||||||
{
|
{
|
||||||
regm &= cgstate.allregs | mask(cgstate.BP);
|
regm &= cgstate.allregs | mask(cgstate.BP) | INSTR.FLOATREGS;
|
||||||
if (!regm)
|
if (!regm)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -2092,6 +2093,7 @@ void fixresult(ref CodeBuilder cdb, elem* e, regm_t retregs, ref regm_t outretre
|
||||||
* Extra information about each CLIB runtime library function.
|
* Extra information about each CLIB runtime library function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
private
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
INF32 = 1, /// if 32 bit only
|
INF32 = 1, /// if 32 bit only
|
||||||
|
@ -2102,6 +2104,7 @@ enum
|
||||||
INFpusheabcdx = 0x20, /// pass EAX/EBX/ECX/EDX on stack, callee does ret 16
|
INFpusheabcdx = 0x20, /// pass EAX/EBX/ECX/EDX on stack, callee does ret 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private
|
||||||
struct ClibInfo
|
struct ClibInfo
|
||||||
{
|
{
|
||||||
regm_t retregs16; /* registers that 16 bit result is returned in */
|
regm_t retregs16; /* registers that 16 bit result is returned in */
|
||||||
|
@ -2114,6 +2117,7 @@ struct ClibInfo
|
||||||
|
|
||||||
int clib_inited = false; // true if initialized
|
int clib_inited = false; // true if initialized
|
||||||
|
|
||||||
|
private
|
||||||
Symbol* symboly(string name, regm_t desregs)
|
Symbol* symboly(string name, regm_t desregs)
|
||||||
{
|
{
|
||||||
Symbol* s = symbol_calloc(name);
|
Symbol* s = symbol_calloc(name);
|
||||||
|
@ -2125,6 +2129,7 @@ Symbol* symboly(string name, regm_t desregs)
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private
|
||||||
void initClibInfo(ref Symbol*[CLIB.MAX] clibsyms, ref ClibInfo[CLIB.MAX] clibinfo)
|
void initClibInfo(ref Symbol*[CLIB.MAX] clibsyms, ref ClibInfo[CLIB.MAX] clibinfo)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < CLIB.MAX; ++i)
|
for (size_t i = 0; i < CLIB.MAX; ++i)
|
||||||
|
@ -2139,6 +2144,7 @@ void initClibInfo(ref Symbol*[CLIB.MAX] clibsyms, ref ClibInfo[CLIB.MAX] clibinf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private
|
||||||
void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t objfmt, exefmt_t exe)
|
void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t objfmt, exefmt_t exe)
|
||||||
{
|
{
|
||||||
const uint ex_unix = (EX_LINUX | EX_LINUX64 |
|
const uint ex_unix = (EX_LINUX | EX_LINUX64 |
|
||||||
|
@ -2805,6 +2811,7 @@ void getClibFunction(uint clib, ref Symbol* s, ref ClibInfo* cinfo, objfmt_t obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private
|
||||||
void getClibInfo(uint clib, Symbol** ps, ClibInfo** pinfo, objfmt_t objfmt, exefmt_t exe)
|
void getClibInfo(uint clib, Symbol** ps, ClibInfo** pinfo, objfmt_t objfmt, exefmt_t exe)
|
||||||
{
|
{
|
||||||
static Symbol*[CLIB.MAX] clibsyms;
|
static Symbol*[CLIB.MAX] clibsyms;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue