mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its Identifier, which should be useful elsewhere too. Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
This commit is contained in:
@@ -1160,7 +1160,7 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
|
||||
uinteger_t i = e2->toInteger();
|
||||
|
||||
if (i >= es1->len)
|
||||
e1->error("string index %ju is out of bounds [0 .. %zu]", i, es1->len);
|
||||
e1->error("string index %llu is out of bounds [0 .. %"PRIuSIZE"]", i, es1->len);
|
||||
else
|
||||
{ unsigned value = es1->charAt(i);
|
||||
e = new IntegerExp(loc, value, type);
|
||||
@@ -1172,7 +1172,8 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
|
||||
uinteger_t i = e2->toInteger();
|
||||
|
||||
if (i >= length)
|
||||
{ e2->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
|
||||
{
|
||||
e2->error("array index %llu is out of bounds %s[0 .. %llu]", i, e1->toChars(), length);
|
||||
}
|
||||
else if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
|
||||
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
|
||||
@@ -1187,7 +1188,8 @@ Expression *Index(Type *type, Expression *e1, Expression *e2)
|
||||
if (e1->op == TOKarrayliteral && !e1->checkSideEffect(2))
|
||||
{ ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
|
||||
if (i >= ale->elements->dim)
|
||||
{ e2->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
|
||||
{
|
||||
e2->error("array index %llu is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
|
||||
}
|
||||
else
|
||||
{ e = (Expression *)ale->elements->data[i];
|
||||
@@ -1237,7 +1239,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
|
||||
uinteger_t iupr = upr->toInteger();
|
||||
|
||||
if (iupr > es1->len || ilwr > iupr)
|
||||
e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
|
||||
e1->error("string slice [%llu .. %llu] is out of bounds", ilwr, iupr);
|
||||
else
|
||||
{ integer_t value;
|
||||
void *s;
|
||||
@@ -1264,7 +1266,7 @@ Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
|
||||
uinteger_t iupr = upr->toInteger();
|
||||
|
||||
if (iupr > es1->elements->dim || ilwr > iupr)
|
||||
e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr);
|
||||
e1->error("array slice [%llu .. %llu] is out of bounds", ilwr, iupr);
|
||||
else
|
||||
{
|
||||
Expressions *elements = new Expressions();
|
||||
|
||||
@@ -675,7 +675,7 @@ void VarDeclaration::semantic(Scope *sc)
|
||||
{ Argument *arg = Argument::getNth(tt->arguments, i);
|
||||
|
||||
OutBuffer buf;
|
||||
buf.printf("_%s_field_%zu", ident->toChars(), i);
|
||||
buf.printf("_%s_field_%"PRIuSIZE, ident->toChars(), i);
|
||||
buf.writeByte(0);
|
||||
char *name = (char *)buf.extractData();
|
||||
Identifier *id = new Identifier(name, TOKidentifier);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
#include "dsymbol.h"
|
||||
#include "lexer.h"
|
||||
@@ -24,6 +25,7 @@
|
||||
struct Expression;
|
||||
struct Statement;
|
||||
struct LabelDsymbol;
|
||||
struct LabelStatement;
|
||||
struct Initializer;
|
||||
struct Module;
|
||||
struct InlineScanState;
|
||||
@@ -611,6 +613,11 @@ struct FuncDeclaration : Declaration
|
||||
// llvmdc stuff
|
||||
bool runTimeHack;
|
||||
std::set<VarDeclaration*> nestedVars;
|
||||
|
||||
// we keep our own table of label statements as LabelDsymbolS
|
||||
// don't always carry their corresponding statement along ...
|
||||
typedef std::map<const char*, LabelStatement*> LabelMap;
|
||||
LabelMap labmap;
|
||||
};
|
||||
|
||||
struct FuncAliasDeclaration : FuncDeclaration
|
||||
|
||||
@@ -52,7 +52,7 @@ void Expression::dump(int i)
|
||||
void IntegerExp::dump(int i)
|
||||
{
|
||||
indent(i);
|
||||
printf("%p %jd type=%s\n", this, (intmax_t)value, type_print(type));
|
||||
printf("%p %lld type=%s\n", this, (intmax_t)value, type_print(type));
|
||||
}
|
||||
|
||||
void IdentifierExp::dump(int i)
|
||||
|
||||
@@ -405,7 +405,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
size_t nparams = Argument::dim(tf->parameters);
|
||||
|
||||
if (nargs > nparams && tf->varargs == 0)
|
||||
error(loc, "expected %zu arguments, not %zu", nparams, nargs);
|
||||
error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
|
||||
|
||||
n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
|
||||
|
||||
@@ -429,7 +429,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
{
|
||||
if (tf->varargs == 2 && i + 1 == nparams)
|
||||
goto L2;
|
||||
error(loc, "expected %zu arguments, not %zu", nparams, nargs);
|
||||
error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
|
||||
break;
|
||||
}
|
||||
arg = p->defaultArg->copy();
|
||||
@@ -443,7 +443,7 @@ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *argume
|
||||
if (arg->implicitConvTo(p->type))
|
||||
{
|
||||
if (nargs != nparams)
|
||||
error(loc, "expected %zu arguments, not %zu", nparams, nargs);
|
||||
error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
|
||||
goto L1;
|
||||
}
|
||||
L2:
|
||||
@@ -1050,8 +1050,7 @@ char *IntegerExp::toChars()
|
||||
return Expression::toChars();
|
||||
#else
|
||||
static char buffer[sizeof(value) * 3 + 1];
|
||||
|
||||
sprintf(buffer, "%jd", value);
|
||||
sprintf(buffer, "%lld", value);
|
||||
return buffer;
|
||||
#endif
|
||||
}
|
||||
@@ -1228,11 +1227,11 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
break;
|
||||
|
||||
case Tint64:
|
||||
buf->printf("%jdL", v);
|
||||
buf->printf("%lldL", v);
|
||||
break;
|
||||
|
||||
case Tuns64:
|
||||
buf->printf("%juLU", v);
|
||||
buf->printf("%lluLU", v);
|
||||
break;
|
||||
|
||||
case Tbit:
|
||||
@@ -1254,17 +1253,17 @@ void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||
}
|
||||
}
|
||||
else if (v & 0x8000000000000000LL)
|
||||
buf->printf("0x%jx", v);
|
||||
buf->printf("0x%llx", v);
|
||||
else
|
||||
buf->printf("%jd", v);
|
||||
buf->printf("%lld", v);
|
||||
}
|
||||
|
||||
void IntegerExp::toMangleBuffer(OutBuffer *buf)
|
||||
{
|
||||
if ((sinteger_t)value < 0)
|
||||
buf->printf("N%jd", -value);
|
||||
buf->printf("N%lld", -value);
|
||||
else
|
||||
buf->printf("%jd", value);
|
||||
buf->printf("%lld", value);
|
||||
}
|
||||
|
||||
/******************************** RealExp **************************/
|
||||
@@ -6469,7 +6468,7 @@ Expression *SliceExp::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
error("string slice [%ju .. %ju] is out of bounds", i1, i2);
|
||||
error("string slice [%llu .. %llu] is out of bounds", i1, i2);
|
||||
e = e1;
|
||||
}
|
||||
return e;
|
||||
@@ -6828,9 +6827,9 @@ Expression *IndexExp::semantic(Scope *sc)
|
||||
}
|
||||
else
|
||||
{
|
||||
error("array index [%ju] is outside array bounds [0 .. %zu]",
|
||||
index, length);
|
||||
e = e1;
|
||||
error("array index [%llu] is outside array bounds [0 .. %"PRIuSIZE"]",
|
||||
index, length);
|
||||
e = e1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -767,7 +767,7 @@ void FuncDeclaration::semantic3(Scope *sc)
|
||||
* because we need it later on.
|
||||
*/
|
||||
OutBuffer buf;
|
||||
buf.printf("_param_%zu", i);
|
||||
buf.printf("_param_%"PRIuSIZE, i);
|
||||
char *name = (char *)buf.extractData();
|
||||
id = new Identifier(name, TOKidentifier);
|
||||
arg->ident = id;
|
||||
|
||||
@@ -382,7 +382,7 @@ Initializer *ArrayInitializer::semantic(Scope *sc, Type *t)
|
||||
}
|
||||
unsigned long amax = 0x80000000;
|
||||
if ((unsigned long) dim * t->next->size() >= amax)
|
||||
error(loc, "array dimension %u exceeds max of %ju", dim, amax / t->next->size());
|
||||
error(loc, "array dimension %u exceeds max of %llu", dim, amax / t->next->size());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,11 +137,11 @@ char *Token::toChars()
|
||||
break;
|
||||
|
||||
case TOKint64v:
|
||||
sprintf(buffer,"%jdL",int64value);
|
||||
sprintf(buffer,"%lldL",int64value);
|
||||
break;
|
||||
|
||||
case TOKuns64v:
|
||||
sprintf(buffer,"%juUL",uns64value);
|
||||
sprintf(buffer,"%lluUL",uns64value);
|
||||
break;
|
||||
|
||||
#if IN_GCC
|
||||
|
||||
@@ -213,7 +213,7 @@ char *TemplateInstance::mangle()
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%zu%s", strlen(id), id);
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("TemplateInstance::mangle() %s = %s\n", toChars(), id);
|
||||
@@ -241,7 +241,7 @@ char *Dsymbol::mangle()
|
||||
p += 2;
|
||||
buf.writestring(p);
|
||||
}
|
||||
buf.printf("%zu%s", strlen(id), id);
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(id), id);
|
||||
id = buf.toChars();
|
||||
buf.data = NULL;
|
||||
//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
|
||||
|
||||
19
dmd/mars.h
19
dmd/mars.h
@@ -16,8 +16,10 @@
|
||||
#endif /* __DMC__ */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <cstdarg>
|
||||
#include <stdarg.h>
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __DMC__
|
||||
#ifdef DEBUG
|
||||
@@ -225,6 +227,19 @@ typedef long double real_t;
|
||||
#include "d-gcc-complex_t.h"
|
||||
#endif
|
||||
|
||||
// taken from GDC
|
||||
// for handling printf incompatibilities
|
||||
#if __MSVCRT__
|
||||
#define PRIuSIZE "Iu"
|
||||
#define PRIxSIZE "Ix"
|
||||
#elif __MINGW32__
|
||||
#define PRIuSIZE "u"
|
||||
#define PRIxSIZE "x"
|
||||
#else
|
||||
#define PRIuSIZE "zu"
|
||||
#define PRIxSIZE "zx"
|
||||
#endif
|
||||
|
||||
struct Module;
|
||||
|
||||
//typedef unsigned Loc; // file location
|
||||
|
||||
16
dmd/mtype.c
16
dmd/mtype.c
@@ -1653,7 +1653,7 @@ d_uns64 TypeSArray::size(Loc loc)
|
||||
return sz;
|
||||
|
||||
Loverflow:
|
||||
error(loc, "index %jd overflow for static array", sz);
|
||||
error(loc, "index %lld overflow for static array", sz);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1721,7 +1721,7 @@ void TypeSArray::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
|
||||
sc = sc->pop();
|
||||
|
||||
if (d >= td->objects->dim)
|
||||
{ error(loc, "tuple index %ju exceeds %u", d, td->objects->dim);
|
||||
{ error(loc, "tuple index %llu exceeds %u", d, td->objects->dim);
|
||||
goto Ldefault;
|
||||
}
|
||||
Object *o = (Object *)td->objects->data[(size_t)d];
|
||||
@@ -1775,7 +1775,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
uinteger_t d = dim->toUInteger();
|
||||
|
||||
if (d >= sd->objects->dim)
|
||||
{ error(loc, "tuple index %ju exceeds %u", d, sd->objects->dim);
|
||||
{ error(loc, "tuple index %llu exceeds %u", d, sd->objects->dim);
|
||||
return Type::terror;
|
||||
}
|
||||
Object *o = (Object *)sd->objects->data[(size_t)d];
|
||||
@@ -1832,7 +1832,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
if (n && n2 / n != d2)
|
||||
{
|
||||
Loverflow:
|
||||
error(loc, "index %jd overflow for static array", d1);
|
||||
error(loc, "index %lld overflow for static array", d1);
|
||||
dim = new IntegerExp(0, 1, tsize_t);
|
||||
}
|
||||
}
|
||||
@@ -1846,7 +1846,7 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
||||
uinteger_t d = dim->toUInteger();
|
||||
|
||||
if (d >= tt->arguments->dim)
|
||||
{ error(loc, "tuple index %ju exceeds %u", d, tt->arguments->dim);
|
||||
{ error(loc, "tuple index %llu exceeds %u", d, tt->arguments->dim);
|
||||
return Type::terror;
|
||||
}
|
||||
Argument *arg = (Argument *)tt->arguments->data[(size_t)d];
|
||||
@@ -1867,7 +1867,7 @@ void TypeSArray::toDecoBuffer(OutBuffer *buf)
|
||||
{
|
||||
buf->writeByte(mangleChar[ty]);
|
||||
if (dim)
|
||||
buf->printf("%ju", dim->toInteger());
|
||||
buf->printf("%llu", dim->toInteger());
|
||||
if (next)
|
||||
next->toDecoBuffer(buf);
|
||||
}
|
||||
@@ -4965,7 +4965,7 @@ Type *TypeSlice::semantic(Loc loc, Scope *sc)
|
||||
uinteger_t i2 = upr->toUInteger();
|
||||
|
||||
if (!(i1 <= i2 && i2 <= tt->arguments->dim))
|
||||
{ error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
|
||||
{ error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, tt->arguments->dim);
|
||||
return Type::terror;
|
||||
}
|
||||
|
||||
@@ -5010,7 +5010,7 @@ void TypeSlice::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol
|
||||
sc = sc->pop();
|
||||
|
||||
if (!(i1 <= i2 && i2 <= td->objects->dim))
|
||||
{ error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, td->objects->dim);
|
||||
{ error(loc, "slice [%llu..%llu] is out of range of [0..%u]", i1, i2, td->objects->dim);
|
||||
goto Ldefault;
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,7 @@ Expression *AddrExp::optimize(int result)
|
||||
TypeSArray *ts = (TypeSArray *)ve->type;
|
||||
integer_t dim = ts->dim->toInteger();
|
||||
if (index < 0 || index >= dim)
|
||||
error("array index %jd is out of bounds [0..%jd]", index, dim);
|
||||
error("array index %lld is out of bounds [0..%lld]", index, dim);
|
||||
e = new SymOffExp(loc, ve->var, index * ts->next->size());
|
||||
e->type = type;
|
||||
return e;
|
||||
@@ -380,7 +380,8 @@ Expression *BinExp::optimize(int result)
|
||||
integer_t i2 = e2->toInteger();
|
||||
d_uns64 sz = e1->type->size() * 8;
|
||||
if (i2 < 0 || i2 > sz)
|
||||
{ error("shift assign by %jd is outside the range 0..%zu", i2, sz);
|
||||
{
|
||||
error("shift assign by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
|
||||
e2 = new IntegerExp(0);
|
||||
}
|
||||
}
|
||||
@@ -475,7 +476,8 @@ Expression *shift_optimize(int result, BinExp *e, Expression *(*shift)(Type *, E
|
||||
integer_t i2 = e->e2->toInteger();
|
||||
d_uns64 sz = e->e1->type->size() * 8;
|
||||
if (i2 < 0 || i2 > sz)
|
||||
{ error("shift by %jd is outside the range 0..%zu", i2, sz);
|
||||
{
|
||||
error("shift by %lld is outside the range 0..%"PRIuSIZE, i2, sz);
|
||||
e->e2 = new IntegerExp(0);
|
||||
}
|
||||
if (e->e1->isConst() == 1)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "root.h"
|
||||
#include "dchar.h"
|
||||
#include "mem.h"
|
||||
#include "mars.h"
|
||||
|
||||
#if 0 //__SC__ //def DEBUG
|
||||
extern "C" void __cdecl _assert(void *e, void *f, unsigned line)
|
||||
@@ -1325,7 +1326,7 @@ void File::stat()
|
||||
void File::checkoffset(size_t offset, size_t nbytes)
|
||||
{
|
||||
if (offset > len || offset + nbytes > len)
|
||||
error("Corrupt file '%s': offset x%zx off end of file",toChars(),offset);
|
||||
error("Corrupt file '%s': offset x%"PRIxSIZE" off end of file",toChars(),offset);
|
||||
}
|
||||
|
||||
char *File::toChars()
|
||||
|
||||
@@ -3519,6 +3519,7 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
|
||||
this->lblock = NULL;
|
||||
this->isReturnLabel = 0;
|
||||
this->llvmBB = NULL;
|
||||
this->asmLabel = false;
|
||||
}
|
||||
|
||||
Statement *LabelStatement::syntaxCopy()
|
||||
@@ -3546,6 +3547,10 @@ Statement *LabelStatement::semantic(Scope *sc)
|
||||
if (statement)
|
||||
statement = statement->semantic(sc);
|
||||
sc->pop();
|
||||
|
||||
// LLVMDC put in labmap
|
||||
fd->labmap[ident->toChars()] = this;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -3605,7 +3610,6 @@ LabelDsymbol::LabelDsymbol(Identifier *ident)
|
||||
: Dsymbol(ident)
|
||||
{
|
||||
statement = NULL;
|
||||
asmLabel = false;
|
||||
}
|
||||
|
||||
LabelDsymbol *LabelDsymbol::isLabel() // is this a LabelDsymbol()?
|
||||
|
||||
@@ -761,13 +761,12 @@ struct LabelStatement : Statement
|
||||
|
||||
// LLVMDC
|
||||
llvm::BasicBlock* llvmBB;
|
||||
bool asmLabel; // for labels inside inline assembler
|
||||
};
|
||||
|
||||
struct LabelDsymbol : Dsymbol
|
||||
{
|
||||
LabelStatement *statement;
|
||||
// LLVMDC
|
||||
bool asmLabel; // for labels inside inline assembler
|
||||
|
||||
LabelDsymbol(Identifier *ident);
|
||||
LabelDsymbol *isLabel();
|
||||
@@ -793,8 +792,8 @@ struct AsmStatement : Statement
|
||||
void toIR(IRState *irs);
|
||||
|
||||
// LLVMDC
|
||||
// non-zero if this is a branch, contains the target
|
||||
LabelDsymbol* isBranchToLabel;
|
||||
// non-zero if this is a branch, contains the target labels identifier
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct AsmBlockStatement : CompoundStatement
|
||||
|
||||
@@ -3444,7 +3444,7 @@ Identifier *TemplateInstance::genIdent()
|
||||
|
||||
//printf("TemplateInstance::genIdent('%s')\n", tempdecl->ident->toChars());
|
||||
id = tempdecl->ident->toChars();
|
||||
buf.printf("__T%zu%s", strlen(id), id);
|
||||
buf.printf("__T%"PRIuSIZE"%s", strlen(id), id);
|
||||
args = tiargs;
|
||||
for (int i = 0; i < args->dim; i++)
|
||||
{ Object *o = (Object *)args->data[i];
|
||||
@@ -3511,7 +3511,7 @@ Identifier *TemplateInstance::genIdent()
|
||||
else
|
||||
{
|
||||
char *p = sa->mangle();
|
||||
buf.printf("%zu%s", strlen(p), p);
|
||||
buf.printf("%"PRIuSIZE"%s", strlen(p), p);
|
||||
}
|
||||
}
|
||||
else if (va)
|
||||
|
||||
@@ -461,16 +461,24 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
// a post-asm switch
|
||||
|
||||
// maps each special value to a goto destination
|
||||
std::map<int, LabelDsymbol*> valToGoto;
|
||||
std::map<int, Identifier*> valToGoto;
|
||||
|
||||
// location of the value containing the index into the valToGoto map
|
||||
// will be set if post-asm dispatcher block is needed
|
||||
llvm::AllocaInst* jump_target;
|
||||
|
||||
{
|
||||
FuncDeclaration* fd = gIR->func()->decl;
|
||||
char* fdmangle = fd->mangle();
|
||||
|
||||
// we use a simple static counter to make sure the new end labels are unique
|
||||
static size_t uniqueLabelsId = 0;
|
||||
std::ostringstream asmGotoEndLabel;
|
||||
asmGotoEndLabel << "." << fdmangle << "__llvm_asm_end" << uniqueLabelsId++;
|
||||
|
||||
// initialize the setter statement we're going to build
|
||||
IRAsmStmt* outSetterStmt = new IRAsmStmt;
|
||||
std::string asmGotoEnd = "jmp __llvm_asm_end ; ";
|
||||
std::string asmGotoEnd = "jmp "+asmGotoEndLabel.str()+" ; ";
|
||||
std::ostringstream code;
|
||||
code << asmGotoEnd;
|
||||
|
||||
@@ -490,7 +498,7 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
end = asmblock->internalLabels.end();
|
||||
bool skip = false;
|
||||
for(it = asmblock->internalLabels.begin(); it != end; ++it)
|
||||
if((*it)->equals(a->isBranchToLabel->ident))
|
||||
if((*it)->equals(a->isBranchToLabel))
|
||||
skip = true;
|
||||
if(skip)
|
||||
continue;
|
||||
@@ -499,11 +507,11 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
valToGoto[n_goto] = a->isBranchToLabel;
|
||||
|
||||
// provide an in-asm target for the branch and set value
|
||||
Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->ident->string);
|
||||
code << a->isBranchToLabel->ident->string << ": ; ";
|
||||
Logger::println("statement '%s' references outer label '%s': creating forwarder", a->code.c_str(), a->isBranchToLabel->string);
|
||||
code << fdmangle << '_' << a->isBranchToLabel->string << ": ; ";
|
||||
code << "movl $<<in" << n_goto << ">>, $<<out0>> ; ";
|
||||
//FIXME: Store the value -> label mapping somewhere, so it can be referenced later
|
||||
outSetterStmt->in.push_back(llvm::ConstantInt::get(llvm::IntegerType::get(32), n_goto));
|
||||
outSetterStmt->in.push_back(DtoConstUint(n_goto));
|
||||
outSetterStmt->in_c += "i,";
|
||||
code << asmGotoEnd;
|
||||
|
||||
@@ -513,11 +521,11 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
{
|
||||
// finalize code
|
||||
outSetterStmt->code = code.str();
|
||||
outSetterStmt->code += "__llvm_asm_end: ; ";
|
||||
outSetterStmt->code += asmGotoEndLabel.str()+": ; ";
|
||||
|
||||
// create storage for and initialize the temporary
|
||||
jump_target = new llvm::AllocaInst(llvm::IntegerType::get(32), "__llvm_jump_target", p->topallocapoint());
|
||||
gIR->ir->CreateStore(llvm::ConstantInt::get(llvm::IntegerType::get(32), 0), jump_target);
|
||||
gIR->ir->CreateStore(DtoConstUint(0), jump_target);
|
||||
// setup variable for output from asm
|
||||
outSetterStmt->out_c = "=*m,";
|
||||
outSetterStmt->out.push_back(jump_target);
|
||||
@@ -623,7 +631,7 @@ void AsmBlockStatement::toIR(IRState* p)
|
||||
llvm::SwitchInst* sw = p->ir->CreateSwitch(val, bb, valToGoto.size());
|
||||
|
||||
// add all cases
|
||||
std::map<int, LabelDsymbol*>::iterator it, end = valToGoto.end();
|
||||
std::map<int, Identifier*>::iterator it, end = valToGoto.end();
|
||||
for(it = valToGoto.begin(); it != end; ++it)
|
||||
{
|
||||
llvm::BasicBlock* casebb = llvm::BasicBlock::Create("case", p->topfunc(), bb);
|
||||
|
||||
@@ -1420,6 +1420,8 @@ struct AsmProcessor
|
||||
}
|
||||
|
||||
void addLabel(char* id) {
|
||||
insnTemplate->writestring(sc->func->mangle());
|
||||
insnTemplate->writestring("_");
|
||||
insnTemplate->writestring(id);
|
||||
}
|
||||
|
||||
@@ -1902,7 +1904,7 @@ struct AsmProcessor
|
||||
asmcode->dollarLabel = 1;
|
||||
} else if (e->op == TOKdsymbol) {
|
||||
LabelDsymbol * lbl = (LabelDsymbol *) ((DsymbolExp *) e)->s;
|
||||
stmt->isBranchToLabel = lbl;
|
||||
stmt->isBranchToLabel = lbl->ident;
|
||||
|
||||
use_star = false;
|
||||
addLabel(lbl->ident->toChars());
|
||||
|
||||
@@ -74,7 +74,7 @@ struct IRAsmStmt
|
||||
std::vector<LLValue*> in;
|
||||
|
||||
// if this is nonzero, it contains the target label
|
||||
LabelDsymbol* isBranchToLabel;
|
||||
Identifier* isBranchToLabel;
|
||||
};
|
||||
|
||||
struct IRAsmBlock
|
||||
|
||||
@@ -150,35 +150,58 @@ void DtoAssert(Loc* loc, DValue* msg)
|
||||
gIR->ir->CreateUnreachable();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// LABEL HELPER
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
LabelStatement* DtoLabelStatement(Identifier* ident)
|
||||
{
|
||||
FuncDeclaration* fd = gIR->func()->decl;
|
||||
FuncDeclaration::LabelMap::iterator iter = fd->labmap.find(ident->toChars());
|
||||
if (iter == fd->labmap.end())
|
||||
{
|
||||
if (fd->returnLabel->ident->equals(ident))
|
||||
{
|
||||
assert(fd->returnLabel->statement);
|
||||
return fd->returnLabel->statement;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GOTO HELPER
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
void DtoGoto(Loc* loc, LabelDsymbol* target, TryFinallyStatement* enclosingtryfinally)
|
||||
void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfinally)
|
||||
{
|
||||
assert(!gIR->scopereturned());
|
||||
|
||||
LabelStatement* lblstmt = DtoLabelStatement(target);
|
||||
assert(lblstmt != NULL);
|
||||
|
||||
// if the target label is inside inline asm, error
|
||||
if(target->asmLabel)
|
||||
if(lblstmt->asmLabel)
|
||||
error("cannot goto into inline asm block", loc->toChars());
|
||||
|
||||
if (target->statement->llvmBB == NULL)
|
||||
target->statement->llvmBB = llvm::BasicBlock::Create("label", gIR->topfunc());
|
||||
if (lblstmt->llvmBB == NULL)
|
||||
lblstmt->llvmBB = llvm::BasicBlock::Create("label", gIR->topfunc());
|
||||
|
||||
// find finallys between goto and label
|
||||
TryFinallyStatement* endfinally = enclosingtryfinally;
|
||||
while(endfinally != NULL && endfinally != target->statement->enclosingtryfinally) {
|
||||
while(endfinally != NULL && endfinally != lblstmt->enclosingtryfinally) {
|
||||
endfinally = endfinally->enclosingtryfinally;
|
||||
}
|
||||
|
||||
// error if didn't find tf statement of label
|
||||
if(endfinally != target->statement->enclosingtryfinally)
|
||||
if(endfinally != lblstmt->enclosingtryfinally)
|
||||
error("cannot goto into try block", loc->toChars());
|
||||
|
||||
// emit code for finallys between goto and label
|
||||
DtoFinallyBlocks(enclosingtryfinally, endfinally);
|
||||
|
||||
llvm::BranchInst::Create(target->statement->llvmBB, gIR->scopebb());
|
||||
llvm::BranchInst::Create(lblstmt->llvmBB, gIR->scopebb());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
@@ -13,8 +13,10 @@ void DtoDeleteArray(DValue* arr);
|
||||
// assertion generator
|
||||
void DtoAssert(Loc* loc, DValue* msg);
|
||||
|
||||
// return the LabelStatement from the current function with the given identifier or NULL if not found
|
||||
LabelStatement* DtoLabelStatement(Identifier* ident);
|
||||
// emit goto
|
||||
void DtoGoto(Loc* loc, LabelDsymbol* target, TryFinallyStatement* enclosingtryfinally);
|
||||
void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfinally);
|
||||
|
||||
// generates IR for finally blocks between the 'start' and 'end' statements
|
||||
// will begin with the finally block belonging to 'start' and does not include
|
||||
|
||||
@@ -1045,6 +1045,8 @@ void LabelStatement::toIR(IRState* p)
|
||||
if (p->asmBlock)
|
||||
{
|
||||
IRAsmStmt* a = new IRAsmStmt;
|
||||
a->code += p->func()->decl->mangle();
|
||||
a->code += "_";
|
||||
a->code += ident->toChars();
|
||||
a->code += ":";
|
||||
p->asmBlock->s.push_back(a);
|
||||
@@ -1052,18 +1054,17 @@ void LabelStatement::toIR(IRState* p)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
assert(tf == NULL);
|
||||
|
||||
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
if (llvmBB)
|
||||
llvmBB->moveBefore(oldend);
|
||||
else
|
||||
llvmBB = llvm::BasicBlock::Create("label", p->topfunc(), oldend);
|
||||
|
||||
|
||||
if (!p->scopereturned())
|
||||
llvm::BranchInst::Create(llvmBB, p->scopebb());
|
||||
|
||||
|
||||
p->scope() = IRScope(llvmBB,oldend);
|
||||
}
|
||||
|
||||
@@ -1086,7 +1087,7 @@ void GotoStatement::toIR(IRState* p)
|
||||
llvm::BasicBlock* oldend = gIR->scopeend();
|
||||
llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend);
|
||||
|
||||
DtoGoto(&loc, label, enclosingtryfinally);
|
||||
DtoGoto(&loc, label->ident, enclosingtryfinally);
|
||||
|
||||
p->scope() = IRScope(bb,oldend);
|
||||
}
|
||||
|
||||
@@ -29,9 +29,6 @@ module lifetime;
|
||||
//debug=PRINTF;
|
||||
//debug=PRINTF2;
|
||||
|
||||
// we're not allowed to jump out of asm blocks
|
||||
//version(D_InlineAsm_X86) version = Asm86;
|
||||
|
||||
private
|
||||
{
|
||||
import tango.stdc.stdlib;
|
||||
@@ -213,7 +210,7 @@ extern (C) void* _d_newarrayT(TypeInfo ti, size_t length)
|
||||
if (length == 0 || size == 0)
|
||||
return null;
|
||||
|
||||
version (Asm86)
|
||||
version (D_InlineAsm_X86)
|
||||
{
|
||||
asm
|
||||
{
|
||||
@@ -252,7 +249,7 @@ extern (C) void* _d_newarrayiT(TypeInfo ti, size_t length)
|
||||
auto initializer = ti.next.init();
|
||||
auto isize = initializer.length;
|
||||
auto q = initializer.ptr;
|
||||
version (Asm86)
|
||||
version (D_InlineAsm_X86)
|
||||
{
|
||||
asm
|
||||
{
|
||||
@@ -515,7 +512,7 @@ body
|
||||
|
||||
if (newlength)
|
||||
{
|
||||
version (Asm86)
|
||||
version (D_InlineAsm_X86)
|
||||
{
|
||||
size_t newsize = void;
|
||||
|
||||
@@ -614,7 +611,7 @@ body
|
||||
|
||||
if (newlength)
|
||||
{
|
||||
version (Asm86)
|
||||
version (D_InlineAsm_X86)
|
||||
{
|
||||
size_t newsize = void;
|
||||
|
||||
|
||||
@@ -24,10 +24,10 @@ MD=mkdir -p
|
||||
CFLAGS=-g $(ADD_CFLAGS)
|
||||
|
||||
#DFLAGS=-release -O3 -inline -w $(ADD_DFLAGS)
|
||||
DFLAGS=-g -w -noasm $(ADD_DFLAGS)
|
||||
DFLAGS=-g -w $(ADD_DFLAGS)
|
||||
|
||||
#TFLAGS=-O3 -inline -w $(ADD_DFLAGS)
|
||||
TFLAGS=-g -w -noasm $(ADD_DFLAGS)
|
||||
TFLAGS=-g -w $(ADD_DFLAGS)
|
||||
|
||||
DOCFLAGS=-version=DDoc
|
||||
|
||||
|
||||
@@ -70,8 +70,7 @@ extern (C) void gc_term()
|
||||
// NOTE: Due to popular demand, this has been re-enabled. It still has
|
||||
// the problems mentioned above though, so I guess we'll see.
|
||||
|
||||
// FIXME: LLVMDC crashes ...
|
||||
//_gc.fullCollectNoStack(); // not really a 'collect all' -- still scans
|
||||
_gc.fullCollectNoStack(); // not really a 'collect all' -- still scans
|
||||
// static data area, roots, and ranges.
|
||||
_gc.Dtor();
|
||||
}
|
||||
|
||||
41
tangotests/asm7.d
Normal file
41
tangotests/asm7.d
Normal file
@@ -0,0 +1,41 @@
|
||||
module tangotests.asm7;
|
||||
|
||||
// test massive label collisions (runtime uses Loverflow too)
|
||||
|
||||
void main()
|
||||
{
|
||||
int a = add(1,2);
|
||||
int s = sub(1,2);
|
||||
assert(a == 3);
|
||||
assert(s == -1);
|
||||
}
|
||||
|
||||
int add(int a, int b)
|
||||
{
|
||||
int res;
|
||||
asm
|
||||
{
|
||||
mov EAX, a;
|
||||
add EAX, b;
|
||||
jo Loverflow;
|
||||
mov res, EAX;
|
||||
}
|
||||
return res;
|
||||
Loverflow:
|
||||
assert(0, "add overflow");
|
||||
}
|
||||
|
||||
int sub(int a, int b)
|
||||
{
|
||||
int res;
|
||||
asm
|
||||
{
|
||||
mov EAX, a;
|
||||
sub EAX, b;
|
||||
jo Loverflow;
|
||||
mov res, EAX;
|
||||
}
|
||||
return res;
|
||||
Loverflow:
|
||||
assert(0, "sub overflow");
|
||||
}
|
||||
Reference in New Issue
Block a user