mirror of
https://github.com/dlang/dmd.git
synced 2025-04-25 12:40:11 +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.
|
||||
*/
|
||||
|
|
|
@ -68,7 +68,7 @@ nothrow:
|
|||
@trusted
|
||||
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)
|
||||
regsave.alignment = REGSIZE;
|
||||
idx = regsave.idx;
|
||||
|
@ -96,7 +96,7 @@ void REGSAVE_save(ref REGSAVE regsave, ref CodeBuilder cdb, reg_t reg, out uint
|
|||
@trusted
|
||||
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]
|
||||
code cs;
|
||||
cs.reg = reg;
|
||||
|
|
|
@ -37,6 +37,7 @@ import dmd.backend.ty;
|
|||
import dmd.backend.type;
|
||||
import dmd.backend.x86.xmm;
|
||||
import dmd.backend.arm.cod1;
|
||||
import dmd.backend.arm.instr : INSTR;
|
||||
|
||||
import dmd.backend.cg : segfl, stackfl;
|
||||
|
||||
|
@ -349,7 +350,7 @@ uint gensaverestore(regm_t regm,ref CodeBuilder cdbsave,ref CodeBuilder cdbresto
|
|||
|
||||
if (cgstate.AArch64)
|
||||
{
|
||||
regm &= cgstate.allregs | mask(cgstate.BP);
|
||||
regm &= cgstate.allregs | mask(cgstate.BP) | INSTR.FLOATREGS;
|
||||
if (!regm)
|
||||
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.
|
||||
*/
|
||||
|
||||
private
|
||||
enum
|
||||
{
|
||||
INF32 = 1, /// if 32 bit only
|
||||
|
@ -2102,6 +2104,7 @@ enum
|
|||
INFpusheabcdx = 0x20, /// pass EAX/EBX/ECX/EDX on stack, callee does ret 16
|
||||
}
|
||||
|
||||
private
|
||||
struct ClibInfo
|
||||
{
|
||||
regm_t retregs16; /* registers that 16 bit result is returned in */
|
||||
|
@ -2114,6 +2117,7 @@ struct ClibInfo
|
|||
|
||||
int clib_inited = false; // true if initialized
|
||||
|
||||
private
|
||||
Symbol* symboly(string name, regm_t desregs)
|
||||
{
|
||||
Symbol* s = symbol_calloc(name);
|
||||
|
@ -2125,6 +2129,7 @@ Symbol* symboly(string name, regm_t desregs)
|
|||
return s;
|
||||
}
|
||||
|
||||
private
|
||||
void initClibInfo(ref Symbol*[CLIB.MAX] clibsyms, ref ClibInfo[CLIB.MAX] clibinfo)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
static Symbol*[CLIB.MAX] clibsyms;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue