Skip to content

Commit

Permalink
ImportC: support dllimport, dllexport, naked attributes (#15048)
Browse files Browse the repository at this point in the history
* ImportC: add more support for naked, dllimport, dllexport

* ImportC: support dllimport, dllexport, naked attributes
  • Loading branch information
WalterBright committed Apr 12, 2023
1 parent 5cd6f80 commit 1ab73ce
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 16 deletions.
57 changes: 44 additions & 13 deletions compiler/src/dmd/cparse.d
Expand Up @@ -1958,6 +1958,7 @@ final class CParser(AST) : Parser!AST
if (specifier.scw & SCW.x_Thread_local)
error("functions cannot be `_Thread_local`"); // C11 6.7.1-4
auto fd = new AST.FuncDeclaration(token.loc, Loc.initial, id, specifiersToSTC(level, specifier), dt, specifier.noreturn);
specifiersToFuncDeclaration(fd, specifier);
s = fd;
}
else
Expand All @@ -1967,7 +1968,9 @@ final class CParser(AST) : Parser!AST
if (!hasInitializer &&
!(specifier.scw & (SCW.xextern | SCW.xstatic | SCW.x_Thread_local) || level == LVL.global))
initializer = new AST.VoidInitializer(token.loc);
s = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
auto vd = new AST.VarDeclaration(token.loc, dt, id, initializer, specifiersToSTC(level, specifier));
specifiersToVarDeclaration(vd, specifier);
s = vd;
}
if (level != LVL.global)
insertIdToTypedefTab(id); // non-typedef declarations can hide typedefs in outer scopes
Expand Down Expand Up @@ -2132,6 +2135,7 @@ final class CParser(AST) : Parser!AST
typedefTab.pop(); // end of function scope

auto fd = new AST.FuncDeclaration(locFunc, prevloc, id, specifiersToSTC(LVL.global, specifier), ft, specifier.noreturn);
specifiersToFuncDeclaration(fd, specifier);

if (addFuncName)
{
Expand Down Expand Up @@ -3182,9 +3186,6 @@ final class CParser(AST) : Parser!AST
/* Check for dllexport, dllimport
* Ignore the rest
*/
bool dllimport; // TODO implement
bool dllexport; // TODO implement
bool naked; // TODO implement
nextToken(); // move past __declspec
check(TOK.leftParenthesis);
while (1)
Expand All @@ -3200,17 +3201,17 @@ final class CParser(AST) : Parser!AST
{
if (token.ident == Id.dllimport)
{
dllimport = true;
specifier.dllimport = true;
nextToken();
}
else if (token.ident == Id.dllexport)
{
dllexport = true;
specifier.dllexport = true;
nextToken();
}
else if (token.ident == Id.naked)
{
naked = true;
specifier.naked = true;
nextToken();
}
else if (token.ident == Id.noreturn)
Expand Down Expand Up @@ -3434,12 +3435,9 @@ final class CParser(AST) : Parser!AST
*/
private void cparseGnuAttribute(ref Specifier specifier)
{
/* Check for dllimport, dllexport, vector_size(bytes)
/* Check for dllimport, dllexport, naked, noreturn, vector_size(bytes)
* Ignore the rest
*/
bool dllimport; // TODO implement
bool dllexport; // TODO implement

if (!isGnuAttributeName())
return;

Expand Down Expand Up @@ -3474,12 +3472,17 @@ final class CParser(AST) : Parser!AST
}
else if (token.ident == Id.dllimport)
{
dllimport = true;
specifier.dllimport = true;
nextToken();
}
else if (token.ident == Id.dllexport)
{
dllexport = true;
specifier.dllexport = true;
nextToken();
}
else if (token.ident == Id.naked)
{
specifier.naked = true;
nextToken();
}
else if (token.ident == Id.noreturn)
Expand Down Expand Up @@ -4888,6 +4891,9 @@ final class CParser(AST) : Parser!AST
struct Specifier
{
bool noreturn; /// noreturn attribute
bool naked; /// naked attribute
bool dllimport; /// dllimport attribute
bool dllexport; /// dllexport attribute
SCW scw; /// storage-class specifiers
MOD mod; /// type qualifiers
AST.Expressions* alignExps; /// alignment
Expand Down Expand Up @@ -4967,6 +4973,31 @@ final class CParser(AST) : Parser!AST
return stc;
}

/***********************
* Add attributes from Specifier to function
* Params:
* fd = function to apply them to
* specifier = specifiers
*/
void specifiersToFuncDeclaration(AST.FuncDeclaration fd, const ref Specifier specifier)
{
fd.isNaked = specifier.naked;
fd.dllImport = specifier.dllimport;
fd.dllExport = specifier.dllexport;
}

/***********************
* Add attributes from Specifier to variable
* Params:
* vd = function to apply them to
* specifier = specifiers
*/
void specifiersToVarDeclaration(AST.VarDeclaration vd, const ref Specifier specifier)
{
vd.dllImport = specifier.dllimport;
vd.dllExport = specifier.dllexport;
}

/***********************
* Return suitable signed integer type for the given size
* Params:
Expand Down
5 changes: 4 additions & 1 deletion compiler/src/dmd/declaration.d
Expand Up @@ -1149,6 +1149,8 @@ extern (C++) class VarDeclaration : Declaration

bool isArgDtorVar; /// temporary created to handle scope destruction of a function argument
bool isCmacro; /// it is a C macro turned into a C declaration
bool dllImport; /// __declspec(dllimport)
bool dllExport; /// __declspec(dllexport)
version (MARS)
{
bool inClosure; /// is inserted into a GC allocated closure
Expand Down Expand Up @@ -1314,7 +1316,7 @@ extern (C++) class VarDeclaration : Declaration

override final bool isExport() const
{
return visibility.kind == Visibility.Kind.export_;
return visibility.kind == Visibility.Kind.export_ || dllExport;
}

override final bool isImportedSymbol() const
Expand All @@ -1325,6 +1327,7 @@ extern (C++) class VarDeclaration : Declaration
* export extern int sym3 = 0; // error, extern cannot have initializer
*/
bool result =
dllImport ||
visibility.kind == Visibility.Kind.export_ &&
storage_class & STC.extern_ &&
(storage_class & STC.static_ || parent.isModule());
Expand Down
4 changes: 4 additions & 0 deletions compiler/src/dmd/declaration.h
Expand Up @@ -675,6 +675,10 @@ class FuncDeclaration : public Declaration
bool isCrtCtor(bool v);
bool isCrtDtor() const;
bool isCrtDtor(bool v);
bool dllImport() const;
bool dllImport(bool v);
bool dllExport() const;
bool dllExport(bool v);

// Data for a function declaration that is needed for the Objective-C
// integration.
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dmd/frontend.h
Expand Up @@ -2528,6 +2528,10 @@ class FuncDeclaration : public Declaration
bool hasEscapingSiblings(bool v);
bool computedEscapingSiblings() const;
bool computedEscapingSiblings(bool v);
bool dllImport() const;
bool dllImport(bool v);
bool dllExport() const;
bool dllExport(bool v);
private:
uint32_t bitFields;
public:
Expand Down Expand Up @@ -6033,6 +6037,10 @@ class VarDeclaration : public Declaration
bool isArgDtorVar(bool v);
bool isCmacro() const;
bool isCmacro(bool v);
bool dllImport() const;
bool dllImport(bool v);
bool dllExport() const;
bool dllExport(bool v);
bool inClosure() const;
bool inClosure(bool v);
bool inAlignSection() const;
Expand Down
8 changes: 6 additions & 2 deletions compiler/src/dmd/func.d
Expand Up @@ -204,6 +204,7 @@ private struct FUNCFLAG
bool hasCatches; /// function has try-catch statements
bool skipCodegen; /// do not generate code for this function.
bool printf; /// is a printf-like function

bool scanf; /// is a scanf-like function
bool noreturn; /// the function does not return
bool isNRVO = true; /// Support for named return value optimization
Expand All @@ -214,11 +215,14 @@ private struct FUNCFLAG
bool hasNoEH; /// No exception unwinding is needed
bool inferRetType; /// Return type is to be inferred
bool hasDualContext; /// has a dual-context 'this' parameter

bool hasAlwaysInlines; /// Contains references to functions that must be inlined
bool isCrtCtor; /// Has attribute pragma(crt_constructor)
bool isCrtDtor; /// Has attribute pragma(crt_destructor)
bool hasEscapingSiblings;/// Has sibling functions that escape
bool computedEscapingSiblings; /// `hasEscapingSiblings` has been computed
bool dllImport; /// __declspec(dllimport)
bool dllExport; /// __declspec(dllexport)
}

/***********************************************************
Expand Down Expand Up @@ -1297,14 +1301,14 @@ extern (C++) class FuncDeclaration : Declaration

override final bool isExport() const
{
return visibility.kind == Visibility.Kind.export_;
return visibility.kind == Visibility.Kind.export_ || dllExport;
}

override final bool isImportedSymbol() const
{
//printf("isImportedSymbol()\n");
//printf("protection = %d\n", visibility);
return (visibility.kind == Visibility.Kind.export_) && !fbody;
return (visibility.kind == Visibility.Kind.export_ || dllImport) && !fbody;
}

override final bool isCodeseg() const pure nothrow @nogc @safe
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dmd/tocsym.d
Expand Up @@ -387,6 +387,9 @@ Symbol *toSymbol(Dsymbol s)
f.Fendline = fd.endloc.linnum ? toSrcpos(fd.endloc) : f.Fstartline;

auto t = Type_toCtype(fd.type);
if (fd.isNaked)
type_setty(&t, t.Tty | mTYnaked);

const msave = t.Tmangle;
if (fd.isMain())
{
Expand Down
31 changes: 31 additions & 0 deletions compiler/test/compilable/cattributes.i
@@ -0,0 +1,31 @@
/* Smoke test dllimport, dllexport, and naked attributes */

__declspec(dllimport) int abc;

__declspec(dllimport) int def();

__declspec(dllexport) int ghi() { return 3; }

__declspec(dllexport) int jkl;

__declspec(naked) __declspec(dllexport)
int test(int a, int b, int c, int d, int e, int f)
{
return a + b + c + d + e + f + abc + def() + ghi() + jkl;
}

/*****************************************/

__attribute__((dllimport)) int abcx;

__attribute__((dllimport)) int defx();

__attribute__((dllexport)) int ghix() { return 3; }

__attribute__((dllexport)) int jklx;

__attribute__((naked)) __attribute__((dllexport))
int testx(int a, int b, int c, int d, int e, int f)
{
return a + b + c + d + e + f + abcx + defx() + ghix() + jklx;
}

0 comments on commit 1ab73ce

Please sign in to comment.