Skip to content
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

Issue 1829 - Allow labels as inline asm operands #3483

Merged
1 commit merged into from Dec 6, 2014
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
92 changes: 48 additions & 44 deletions src/iasm.c
Expand Up @@ -1383,38 +1383,45 @@ static code *asm_emit(Loc loc,
popndTmp->pregDisp2 &&
popndTmp->pregDisp2->val == _BP)
usDefaultseg = _SS;
else if (asmstate.ucItype == ITjump)
usDefaultseg = _CS;
else
usDefaultseg = _DS;
if (pregSegment->val != usDefaultseg)
switch (pregSegment->val)
{
case _CS:
emit(0x2e);
pc->Iflags |= CFcs;
break;
case _SS:
emit(0x36);
pc->Iflags |= CFss;
break;
case _DS:
emit(0x3e);
pc->Iflags |= CFds;
break;
case _ES:
emit(0x26);
pc->Iflags |= CFes;
break;
case _FS:
emit(0x64);
pc->Iflags |= CFfs;
break;
case _GS:
emit(0x65);
pc->Iflags |= CFgs;
break;
default:
assert(0);
}
{
if (asmstate.ucItype == ITjump)
error(asmstate.loc, "Cannot generate a segment prefix for a branching instruction");
else
switch (pregSegment->val)
{
case _CS:
emit(0x2e);
pc->Iflags |= CFcs;
break;
case _SS:
emit(0x36);
pc->Iflags |= CFss;
break;
case _DS:
emit(0x3e);
pc->Iflags |= CFds;
break;
case _ES:
emit(0x26);
pc->Iflags |= CFes;
break;
case _FS:
emit(0x64);
pc->Iflags |= CFfs;
break;
case _GS:
emit(0x65);
pc->Iflags |= CFgs;
break;
default:
assert(0);
}
}
}
break;
}
Expand Down Expand Up @@ -4311,6 +4318,8 @@ static OPND *asm_primary_exp()
o1->segreg = regp;
asm_token();
o2 = asm_cond_exp();
if (o2->s && o2->s->isLabel())
o2->segreg = NULL; // The segment register was specified explicitly.
o1 = asm_merge_opnds(o1, o2);
}
else if (asm_TKlbra_seen)
Expand Down Expand Up @@ -4354,23 +4363,18 @@ static OPND *asm_primary_exp()
}
else
{
if (asmstate.ucItype == ITjump)
{
s = NULL;
if (asmstate.sc->func->labtab)
s = asmstate.sc->func->labtab->lookup(asmtok->ident);
if (!s)
s = asmstate.sc->search(Loc(), asmtok->ident, &scopesym);
if (!s)
{
// Assume it is a label, and define that label
s = asmstate.sc->func->searchLabel(asmtok->ident);
}
}
else
s = NULL;
if (asmstate.sc->func->labtab)
s = asmstate.sc->func->labtab->lookup(asmtok->ident);
if (!s)
s = asmstate.sc->search(Loc(), asmtok->ident, &scopesym);
if (!s)
asmerr("undefined identifier '%s'", asmtok->toChars());
{
// Assume it is a label, and define that label
s = asmstate.sc->func->searchLabel(asmtok->ident);
}
if (s->isLabel())
o1->segreg = &regtab[25]; // Make it use CS as a base for a label

Identifier *id = asmtok->ident;
asm_token();
Expand Down
35 changes: 35 additions & 0 deletions test/compilable/iasm_labeloperand.d
@@ -0,0 +1,35 @@

version (D_InlineAsm_X86)
version = TestInlineAsm;
else version (D_InlineAsm_X86_64)
version = TestInlineAsm;
else
pragma(msg, "Inline asm not supported, not testing.");

version (TestInlineAsm)
{
void testInlineAsm()
{
asm
{
L1:
nop;
nop;
nop;
nop;

mov EAX, dword ptr L1; // Check back references
mov EAX, dword ptr L2; // Check forward references
mov EAX, dword ptr DS:L1; // Not really useful in standard use, but who knows.
mov EAX, dword ptr FS:L2; // Once again, not really useful, but it is valid.
mov EAX, dword ptr CS:L1; // This is what the first test case should implicitly be.

L2:
nop;
nop;
nop;
nop;

}
}
}
21 changes: 21 additions & 0 deletions test/fail_compilation/fail12635.d
@@ -0,0 +1,21 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail12635.d(19): Error: Cannot generate a segment prefix for a branching instruction
---
*/

void foo()
{
enum NOP = 0x9090_9090_9090_9090;

asm
{
L1:
dq NOP,NOP,NOP,NOP; // 32
dq NOP,NOP,NOP,NOP; // 64
dq NOP,NOP,NOP,NOP; // 96
dq NOP,NOP,NOP,NOP; // 128
jmp DS:L1;
}
}