diff gen/naked.cpp @ 920:545f54041d91

Implemented proper support for naked asm using llvm module level asm. Still not 100% complete, but already 1000 times better that what we had before. Don's BignumX86 implementation from Tango (when turned into a standalone unittest) seems to fully work with no changes, and great performance :) Fixed align N; in asm blocks. Fixed inreg parameter passing on x86 for ref/out params. Removed support for lazy initialization of function local static variables, I have no idea why I ever implemented this, it's not in the D spec, and DMD doesn't support it :P Some of the global variable related changes might cause minor regressions, but they should be easily fixable.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 03 Feb 2009 08:54:57 +0100
parents
children 9bab304ed531
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/naked.cpp	Tue Feb 03 08:54:57 2009 +0100
@@ -0,0 +1,140 @@
+#include "gen/llvm.h"
+
+#include "expression.h"
+#include "statement.h"
+#include "declaration.h"
+
+#include <cassert>
+
+#include "gen/logger.h"
+#include "gen/irstate.h"
+#include "gen/llvmhelpers.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void Statement::toNakedIR(IRState *p)
+{
+    error("not allowed in naked function");
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void CompoundStatement::toNakedIR(IRState *p)
+{
+    Logger::println("CompoundStatement::toNakedIR(): %s", loc.toChars());
+    LOG_SCOPE;
+
+    if (statements)
+    for (unsigned i = 0; i < statements->dim; i++)
+    {
+        Statement* s = (Statement*)statements->data[i];
+        if (s) s->toNakedIR(p);
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void ExpStatement::toNakedIR(IRState *p)
+{
+    Logger::println("ExpStatement::toNakedIR(): %s", loc.toChars());
+    LOG_SCOPE;
+
+    // only expstmt supported in declarations
+    if (exp->op != TOKdeclaration)
+    {
+        Statement::toNakedIR(p);
+        return;
+    }
+
+    DeclarationExp* d = (DeclarationExp*)exp;
+    VarDeclaration* vd = d->declaration->isVarDeclaration();
+    FuncDeclaration* fd = d->declaration->isFuncDeclaration();
+    EnumDeclaration* ed = d->declaration->isEnumDeclaration();
+
+    // and only static variable/function declaration
+    // no locals or nested stuffies!
+    if (!vd && !fd && !ed)
+    {
+        Statement::toNakedIR(p);
+        return;
+    }
+    else if (vd && !vd->isDataseg())
+    {
+        error("non-static variable '%s' not allowed in naked function", vd->toChars());
+        return;
+    }
+    else if (fd && !fd->isStatic())
+    {
+        error("non-static nested function '%s' not allowed in naked function", fd->toChars());
+        return;
+    }
+    // enum decls should always be safe
+
+    // make sure the symbols gets processed
+    d->declaration->toObjFile(0);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void LabelStatement::toNakedIR(IRState *p)
+{
+    Logger::println("LabelStatement::toNakedIR(): %s", loc.toChars());
+    LOG_SCOPE;
+
+    p->nakedAsm << p->func()->decl->mangle() << "_" << ident->toChars() << ":";
+
+    if (statement)
+        statement->toNakedIR(p);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+void DtoDefineNakedFunction(FuncDeclaration* fd)
+{
+    Logger::println("DtoDefineNakedFunction(%s)", fd->mangle());
+    LOG_SCOPE;
+
+    assert(fd->ir.irFunc);
+    gIR->functions.push_back(fd->ir.irFunc);
+
+    // we need to do special processing on the body, since we only want
+    // to allow actual inline asm blocks to reach the final asm output
+
+    std::ostringstream& asmstr = gIR->nakedAsm;
+
+    // build function header
+
+    // REALLY FIXME: this is most likely extremely platform dependent
+
+    const char* mangle = fd->mangle();
+    const char* linkage = "globl";
+    std::string section = "text";
+    unsigned align = 16;
+
+    std::ostringstream tmpstr;
+
+    if (DtoIsTemplateInstance(fd))
+    {
+        linkage = "weak";
+        tmpstr << "section\t.gnu.linkonce.t." << mangle << ",\"ax\",@progbits";
+        section = tmpstr.str();
+    }
+
+    asmstr << "\t." << section << std::endl;
+    asmstr << "\t.align\t" << align << std::endl;
+    asmstr << "\t." << linkage << "\t" << mangle << std::endl;
+    asmstr << "\t.type\t" << mangle << ",@function" << std::endl;
+    asmstr << mangle << ":" << std::endl;
+
+    // emit body
+    fd->fbody->toNakedIR(gIR);
+
+    // emit size after body
+    // why? dunno, llvm seems to do it by default ..
+    asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl << std::endl;
+
+    gIR->module->appendModuleInlineAsm(asmstr.str());
+    asmstr.str("");
+
+    gIR->functions.pop_back();
+}