Skip to content

Commit

Permalink
Merge pull request #3483 from Orvid/labeloperands
Browse files Browse the repository at this point in the history
Issue 1829 - Allow labels as inline asm operands
  • Loading branch information
AndrejMitrovic committed Dec 6, 2014
2 parents 3a46cef + 4e95218 commit c94f831
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 44 deletions.
92 changes: 48 additions & 44 deletions src/iasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1384,38 +1384,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 @@ -4312,6 +4319,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 @@ -4355,23 +4364,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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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;
}
}

0 comments on commit c94f831

Please sign in to comment.