Skip to content

fix Issue 24130 - ImportC: Windows headers use inline asm with differ… #15595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dmd/cli.d
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ dmd -cov -unittest myprog.d
Option("nothrow",
"assume no Exceptions will be thrown",
`Turns off generation of exception stack unwinding code, enables
more efficient code for RAII objects.`,
more efficient code for RAII objects.`,
),
Option("O",
"optimize",
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dmd/cparse.d
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ final class CParser(AST) : Parser!AST

default:
// ImportC extensions: parse as a D asm block.
s = parseAsm();
s = parseAsm(compileEnv.masm);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say just pass true instead of relying on...

break;
}
break;
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/dmodule.d
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,9 @@ extern (C++) final class Module : Package
{
filetype = FileType.c;

global.compileEnv.masm = target.os == Target.OS.Windows && !target.omfobj; // Microsoft inline assembler format
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... platform-specific global variables that gdc (and ldc?) don't define or set.

scope p = new CParser!AST(this, buf, cast(bool) docfile, global.errorSink, target.c, &defines, &global.compileEnv);
global.compileEnv.masm = false;
p.nextToken();
checkCompiledImport();
members = p.parseModule();
Expand Down
10 changes: 7 additions & 3 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -3403,6 +3403,7 @@ struct CompileEnv final
bool ddocOutput;
bool shortenedMethods;
bool obsolete;
bool masm;
CompileEnv() :
versionNumber(),
date(),
Expand All @@ -3412,10 +3413,11 @@ struct CompileEnv final
previewIn(),
ddocOutput(),
shortenedMethods(true),
obsolete()
obsolete(),
masm()
{
}
CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool shortenedMethods = true, bool obsolete = false) :
CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool shortenedMethods = true, bool obsolete = false, bool masm = false) :
versionNumber(versionNumber),
date(date),
time(time),
Expand All @@ -3424,7 +3426,8 @@ struct CompileEnv final
previewIn(previewIn),
ddocOutput(ddocOutput),
shortenedMethods(shortenedMethods),
obsolete(obsolete)
obsolete(obsolete),
masm(masm)
{}
};

Expand Down Expand Up @@ -4237,6 +4240,7 @@ class AsmStatement : public Statement
{
public:
Token* tokens;
bool caseSensitive;
AsmStatement* syntaxCopy() override;
void accept(Visitor* v) override;
};
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dmd/glue.d
Original file line number Diff line number Diff line change
Expand Up @@ -565,10 +565,10 @@ private void genObjFile(Module m, bool multiobj)

outdata(m.cov);

size_t sz = m.covb[0].sizeof;
size_t n = (m.numlines + sz * 8) / (sz * 8);
uint* p = cast(uint*)Mem.check(calloc(n, sz));
m.covb = p[0 .. n];
size_t sz = m.covb[0].sizeof;
size_t n = (m.numlines + sz * 8) / (sz * 8);
uint* p = cast(uint*)Mem.check(calloc(n, sz));
m.covb = p[0 .. n];
}

for (int i = 0; i < m.members.length; i++)
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/iasm.d
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ extern(C++) Statement asmSemantic(AsmStatement s, Scope *sc)
return statementSemantic(se, sc);
}
auto ias = new InlineAsmStatement(s.loc, s.tokens);
ias.caseSensitive = s.caseSensitive;
return inlineAsmSemantic(ias, sc);
}
else version (IN_GCC)
Expand Down
61 changes: 52 additions & 9 deletions compiler/src/dmd/iasmdmd.d
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,15 @@ immutable:
ubyte val;
opflag_t ty;

bool isSIL_DIL_BPL_SPL() const @safe
bool isSIL_DIL_BPL_SPL() const @trusted
{
bool caseSensitive = asmstate.statement.caseSensitive;
// Be careful as these have the same val's as AH CH DH BH
return ty == _r8 &&
((val == _SIL && regstr == "SIL") ||
(val == _DIL && regstr == "DIL") ||
(val == _BPL && regstr == "BPL") ||
(val == _SPL && regstr == "SPL"));
((val == _SIL && stringEq(regstr, "SIL", caseSensitive)) ||
(val == _DIL && stringEq(regstr, "DIL", caseSensitive)) ||
(val == _BPL && stringEq(regstr, "BPL", caseSensitive)) ||
(val == _SPL && stringEq(regstr, "SPL", caseSensitive)));
}
}

Expand Down Expand Up @@ -2161,9 +2162,9 @@ private @safe pure bool asm_isNonZeroInt(const ref OPND o)
/*******************************
*/

private @safe pure bool asm_is_fpreg(const(char)[] szReg)
private @trusted bool asm_is_fpreg(const(char)[] szReg)
{
return szReg == "ST";
return stringEq(szReg, "ST", asmstate.statement.caseSensitive);
}

/*******************************
Expand Down Expand Up @@ -3395,9 +3396,10 @@ immutable(REG)* asm_reg_lookup(const(char)[] s)
{
//dbg_printf("asm_reg_lookup('%s')\n",s);

bool caseSensitive = asmstate.statement.caseSensitive;
for (int i = 0; i < regtab.length; i++)
{
if (s == regtab[i].regstr)
if (stringEq(s, regtab[i].regstr, caseSensitive))
{
return &regtab[i];
}
Expand All @@ -3406,7 +3408,7 @@ immutable(REG)* asm_reg_lookup(const(char)[] s)
{
for (int i = 0; i < regtab64.length; i++)
{
if (s == regtab64[i].regstr)
if (stringEq(s, regtab64[i].regstr, caseSensitive))
{
return &regtab64[i];
}
Expand Down Expand Up @@ -4648,3 +4650,44 @@ unittest
assert( isOneOf(_8, _anysize));
}
}

/**********************************
* Case insensitive string compare
* Returns: true if equal
*/

bool stringEq(const(char)[] s1, const(char)[] s2, bool caseSensitive)
{
if (caseSensitive)
return s1 == s2;

if (s1.length != s2.length)
return false;
foreach (i, c; s1)
{
char c1 = c;
if ('A' <= c1 && c1 <= 'Z')
c1 |= 0x20;
char c2 = s2[i];
if ('A' <= c2 && c2 <= 'Z')
c2 |= 0x20;

if (c1 != c2)
return false;
}
return true;
}

unittest
{
assert(!stringEq("ABZ", "ABZX", true));

assert( stringEq("ABZ", "ABZ", true));
assert(!stringEq("aBz", "ABZ", true));
assert(!stringEq("ABZ", "ABz", true));

assert( stringEq("aBZ", "ABZ", false));
assert( stringEq("aBz", "AbZ", false));
assert( stringEq("ABZ", "ABz", false));
assert(!stringEq("3BZ", "ABz", false));
}
1 change: 1 addition & 0 deletions compiler/src/dmd/lexer.d
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct CompileEnv
bool ddocOutput; /// collect embedded documentation comments
bool shortenedMethods = true; /// allow => in normal function declarations
bool obsolete; /// warn on use of legacy code
bool masm; /// use MASM inline asm syntax
}

/***********************************************************
Expand Down
18 changes: 15 additions & 3 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -6601,7 +6601,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}

case TOK.asm_:
s = parseAsm();
s = parseAsm(false);
break;

case TOK.import_:
Expand Down Expand Up @@ -6972,10 +6972,12 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
* AsmInstruction ;
* AsmInstruction ; AsmInstruction
*
* Params:
* endOfLine = true if EOL means end of asm statement
* Returns:
* inline assembler block as a Statement
*/
AST.Statement parseAsm()
AST.Statement parseAsm(bool endOfLine)
{
// Parse the asm block into a sequence of AsmStatements,
// each AsmStatement is one instruction.
Expand All @@ -6998,6 +7000,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
size_t nestlevel = 0;
while (1)
{
if (endOfLine)
nextDefineLine();
switch (token.value)
{
case TOK.identifier:
Expand Down Expand Up @@ -7032,14 +7036,20 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
break;

case TOK.endOfLine:
nextDefineLine();
goto case;

case TOK.semicolon:
Comment on lines +7039 to 7043
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it unintentionally bleeds into D code parser. Did you forget an if (endOfLine) { ... }?

if (nestlevel != 0)
error("mismatched number of curly brackets");

if (toklist || label)
{
// Create AsmStatement from list of tokens we've saved
AST.Statement s = new AST.AsmStatement(token.loc, toklist);
AST.AsmStatement as = new AST.AsmStatement(token.loc, toklist);
as.caseSensitive = !endOfLine;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two variables mean different things, why is one setting the other?

AST.Statement s = as;
toklist = null;
ptoklist = &toklist;
if (label)
Expand Down Expand Up @@ -7083,6 +7093,8 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
break;
}
nextToken();
if (token.value == TOK.endOfLine)
nextToken();
auto s = new AST.CompoundAsmStatement(loc, statements, stc);
return s;
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/statement.d
Original file line number Diff line number Diff line change
Expand Up @@ -1958,6 +1958,7 @@ extern (C++) final class LabelDsymbol : Dsymbol
extern (C++) class AsmStatement : Statement
{
Token* tokens;
bool caseSensitive; // for register names

extern (D) this(const ref Loc loc, Token* tokens) @safe
{
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/statement.h
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ class AsmStatement : public Statement
{
public:
Token *tokens;
bool caseSensitive; // for register names

AsmStatement *syntaxCopy() override;
void accept(Visitor *v) override { v->visit(this); }
Expand Down
18 changes: 18 additions & 0 deletions compiler/test/compilable/test24130.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* DISABLED: freebsd32 freebsd64 linux32 linux64 osx32 osx64 win64 dragonflybsd openbsd
*/

// https://issues.dlang.org/show_bug.cgi?id=24130

void test(int ShiftCount, int Value)
{
#ifdef _MSC_VER
__asm {
mov ecx, ShiftCount
mov eax, dword ptr [Value]
mov edx, dword ptr [Value+4]
shrd eax, edx, cl
shr edx, cl
}
#endif
}