mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
Adding a collector name attribute to Function in the IR. These
methods are new to Function: bool hasCollector() const; const std::string &getCollector() const; void setCollector(const std::string &); void clearCollector(); The assembly representation is as such: define void @f() gc "shadow-stack" { ... The implementation uses an on-the-side table to map Functions to collector names, such that there is no overhead. A StringPool is further used to unique collector names, which are extremely likely to be unique per process. llvm-svn: 44769
This commit is contained in:
parent
8430f1ff9a
commit
5d201e0bcc
@ -282,6 +282,8 @@ external is_intrinsic : llvalue -> bool = "llvm_is_intrinsic"
|
||||
external function_call_conv : llvalue -> int = "llvm_function_call_conv"
|
||||
external set_function_call_conv : int -> llvalue -> unit
|
||||
= "llvm_set_function_call_conv"
|
||||
external collector : llvalue -> string option = "llvm_collector"
|
||||
external set_collector : string option -> llvalue -> unit = "llvm_set_collector"
|
||||
|
||||
(* TODO: param attrs *)
|
||||
|
||||
|
@ -754,6 +754,15 @@ external function_call_conv : llvalue -> int = "llvm_function_call_conv"
|
||||
external set_function_call_conv : int -> llvalue -> unit
|
||||
= "llvm_set_function_call_conv"
|
||||
|
||||
(** [collector f] returns [Some name] if the function [f] has a garbage
|
||||
collection algorithm specified and [None] otherwise.
|
||||
See the method [llvm::Function::getCollector]. **)
|
||||
external collector : llvalue -> string option = "llvm_collector"
|
||||
|
||||
(** [set_collector gc f] sets the collection algorithm for the function [f] to
|
||||
[gc]. See the method [llvm::Function::setCollector]. **)
|
||||
external set_collector : string option -> llvalue -> unit = "llvm_set_collector"
|
||||
|
||||
(*--... Operations on basic blocks .........................................--*)
|
||||
|
||||
(** [basic_blocks fn] returns the basic blocks of the function [f].
|
||||
|
@ -536,6 +536,29 @@ CAMLprim value llvm_set_function_call_conv(value Id, LLVMValueRef Fn) {
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/* llvalue -> string option */
|
||||
CAMLprim value llvm_collector(LLVMValueRef Fn) {
|
||||
const char *Collector;
|
||||
CAMLparam0();
|
||||
CAMLlocal2(Name, Option);
|
||||
|
||||
if ((Collector = LLVMGetCollector(Fn))) {
|
||||
Name = copy_string(Collector);
|
||||
|
||||
Option = alloc(1, 0);
|
||||
Field(Option, 0) = Name;
|
||||
CAMLreturn(Option);
|
||||
} else {
|
||||
CAMLreturn(Val_int(0));
|
||||
}
|
||||
}
|
||||
|
||||
/* string option -> llvalue -> unit */
|
||||
CAMLprim value llvm_set_collector(value GC, LLVMValueRef Fn) {
|
||||
LLVMSetCollector(Fn, GC == Val_int(0)? 0 : String_val(Field(GC, 0)));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
/*--... Operations on basic blocks .........................................--*/
|
||||
|
||||
/* llvalue -> llbasicblock array */
|
||||
|
@ -26,6 +26,7 @@
|
||||
<li><a href="#functionstructure">Functions</a></li>
|
||||
<li><a href="#aliasstructure">Aliases</a>
|
||||
<li><a href="#paramattrs">Parameter Attributes</a></li>
|
||||
<li><a href="#gc">Garbage Collector Names</a></li>
|
||||
<li><a href="#moduleasm">Module-Level Inline Assembly</a></li>
|
||||
<li><a href="#datalayout">Data Layout</a></li>
|
||||
</ol>
|
||||
@ -702,15 +703,16 @@ an optional <a href="#linkage">linkage type</a>, an optional
|
||||
<a href="#paramattrs">parameter attribute</a> for the return type, a function
|
||||
name, a (possibly empty) argument list (each with optional
|
||||
<a href="#paramattrs">parameter attributes</a>), an optional section, an
|
||||
optional alignment, an opening curly brace, a list of basic blocks, and a
|
||||
closing curly brace.
|
||||
optional alignment, an optional <a href="gc">garbage collector name</a>, an
|
||||
opening curly brace, a list of basic blocks, and a closing curly brace.
|
||||
|
||||
LLVM function declarations consist of the "<tt>declare</tt>" keyword, an
|
||||
optional <a href="#linkage">linkage type</a>, an optional
|
||||
<a href="#visibility">visibility style</a>, an optional
|
||||
<a href="#callingconv">calling convention</a>, a return type, an optional
|
||||
<a href="#paramattrs">parameter attribute</a> for the return type, a function
|
||||
name, a possibly empty list of arguments, and an optional alignment.</p>
|
||||
name, a possibly empty list of arguments, an optional alignment, and an optional
|
||||
<a href="gc">garbage collector name</a>.</p>
|
||||
|
||||
<p>A function definition contains a list of basic blocks, forming the CFG for
|
||||
the function. Each basic block may optionally start with a label (giving the
|
||||
@ -824,6 +826,23 @@ declare i32 @atoi(i8*) nounwind readonly
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="gc">Garbage Collector Names</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>Each function may specify a garbage collector name, which is simply a
|
||||
string.</p>
|
||||
|
||||
<div class="doc_code"><pre
|
||||
>define void @f() gc "name" { ...</pre></div>
|
||||
|
||||
<p>The compiler declares the supported values of <i>name</i>. Specifying a
|
||||
collector which will cause the compiler to alter its output in order to support
|
||||
the named garbage collection algorithm.</p>
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="moduleasm">Module-Level Inline Assembly</a>
|
||||
|
@ -339,6 +339,8 @@ LLVMValueRef LLVMGetParam(LLVMValueRef Fn, unsigned Index);
|
||||
unsigned LLVMGetIntrinsicID(LLVMValueRef Fn);
|
||||
unsigned LLVMGetFunctionCallConv(LLVMValueRef Fn);
|
||||
void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC);
|
||||
const char *LLVMGetCollector(LLVMValueRef Fn);
|
||||
void LLVMSetCollector(LLVMValueRef Fn, const char *Coll);
|
||||
|
||||
/* Operations on basic blocks */
|
||||
LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef Bb);
|
||||
|
@ -58,7 +58,9 @@ namespace bitc {
|
||||
MODULE_CODE_ALIAS = 9,
|
||||
|
||||
/// MODULE_CODE_PURGEVALS: [numvals]
|
||||
MODULE_CODE_PURGEVALS = 10
|
||||
MODULE_CODE_PURGEVALS = 10,
|
||||
|
||||
MODULE_CODE_COLLECTORNAME = 11 // COLLECTORNAME: [strchr x N]
|
||||
};
|
||||
|
||||
/// PARAMATTR blocks have code for defining a parameter attribute set.
|
||||
|
@ -153,6 +153,13 @@ public:
|
||||
/// @brief Set the parameter attributes.
|
||||
void setParamAttrs(const ParamAttrsList *attrs);
|
||||
|
||||
/// hasCollector/getCollector/setCollector/clearCollector - The name of the
|
||||
/// garbage collection algorithm to use during code generation.
|
||||
bool hasCollector() const;
|
||||
const char *getCollector() const;
|
||||
void setCollector(const char *Str);
|
||||
void clearCollector();
|
||||
|
||||
/// @brief Determine whether the function has the given attribute.
|
||||
bool paramHasAttr(uint16_t i, ParameterAttributes attr) const {
|
||||
return ParamAttrs && ParamAttrs->paramHasAttr(i, attr);
|
||||
|
@ -468,6 +468,7 @@ int LLLexer::LexIdentifier() {
|
||||
KEYWORD("module", MODULE);
|
||||
KEYWORD("asm", ASM_TOK);
|
||||
KEYWORD("sideeffect", SIDEEFFECT);
|
||||
KEYWORD("gc", GC);
|
||||
|
||||
KEYWORD("cc", CC_TOK);
|
||||
KEYWORD("ccc", CCC_TOK);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -181,9 +181,10 @@
|
||||
NEST = 397,
|
||||
READNONE = 398,
|
||||
READONLY = 399,
|
||||
DEFAULT = 400,
|
||||
HIDDEN = 401,
|
||||
PROTECTED = 402
|
||||
GC = 400,
|
||||
DEFAULT = 401,
|
||||
HIDDEN = 402,
|
||||
PROTECTED = 403
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
@ -329,16 +330,17 @@
|
||||
#define NEST 397
|
||||
#define READNONE 398
|
||||
#define READONLY 399
|
||||
#define DEFAULT 400
|
||||
#define HIDDEN 401
|
||||
#define PROTECTED 402
|
||||
#define GC 400
|
||||
#define DEFAULT 401
|
||||
#define HIDDEN 402
|
||||
#define PROTECTED 403
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 945 "/home/asl/proj/llvm/src/lib/AsmParser/llvmAsmParser.y"
|
||||
#line 945 "/Users/malichus/Source/llvm/src/llvm/lib/AsmParser/llvmAsmParser.y"
|
||||
{
|
||||
llvm::Module *ModuleVal;
|
||||
llvm::Function *FunctionVal;
|
||||
@ -385,8 +387,8 @@ typedef union YYSTYPE
|
||||
llvm::ICmpInst::Predicate IPredicate;
|
||||
llvm::FCmpInst::Predicate FPredicate;
|
||||
}
|
||||
/* Line 1489 of yacc.c. */
|
||||
#line 390 "llvmAsmParser.tab.h"
|
||||
/* Line 1529 of yacc.c. */
|
||||
#line 392 "llvmAsmParser.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
|
@ -1046,7 +1046,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
|
||||
%token<StrVal> STRINGCONSTANT ATSTRINGCONSTANT PCTSTRINGCONSTANT
|
||||
%type <StrVal> LocalName OptLocalName OptLocalAssign
|
||||
%type <StrVal> GlobalName OptGlobalAssign GlobalAssign
|
||||
%type <StrVal> OptSection SectionString
|
||||
%type <StrVal> OptSection SectionString OptGC
|
||||
|
||||
%type <UIntVal> OptAlign OptCAlign
|
||||
|
||||
@ -1090,7 +1090,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
|
||||
|
||||
// Function Attributes
|
||||
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
|
||||
%token READNONE READONLY
|
||||
%token READNONE READONLY GC
|
||||
|
||||
// Visibility Styles
|
||||
%token DEFAULT HIDDEN PROTECTED
|
||||
@ -1244,6 +1244,12 @@ OptFuncAttrs : /* empty */ { $$ = ParamAttr::None; }
|
||||
}
|
||||
;
|
||||
|
||||
OptGC : /* empty */ { $$ = 0; }
|
||||
| GC STRINGCONSTANT {
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
// OptAlign/OptCAlign - An optional alignment, and an optional alignment with
|
||||
// a comma before it.
|
||||
OptAlign : /*empty*/ { $$ = 0; } |
|
||||
@ -2225,7 +2231,7 @@ ArgList : ArgListH {
|
||||
};
|
||||
|
||||
FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
|
||||
OptFuncAttrs OptSection OptAlign {
|
||||
OptFuncAttrs OptSection OptAlign OptGC {
|
||||
std::string FunctionName(*$3);
|
||||
delete $3; // Free strdup'd memory!
|
||||
|
||||
@ -2328,6 +2334,10 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
|
||||
Fn->setSection(*$8);
|
||||
delete $8;
|
||||
}
|
||||
if ($10) {
|
||||
Fn->setCollector($10->c_str());
|
||||
delete $10;
|
||||
}
|
||||
|
||||
// Add all of the arguments we parsed to the function...
|
||||
if ($5) { // Is null if empty...
|
||||
|
@ -1046,7 +1046,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
|
||||
%token<StrVal> STRINGCONSTANT ATSTRINGCONSTANT PCTSTRINGCONSTANT
|
||||
%type <StrVal> LocalName OptLocalName OptLocalAssign
|
||||
%type <StrVal> GlobalName OptGlobalAssign GlobalAssign
|
||||
%type <StrVal> OptSection SectionString
|
||||
%type <StrVal> OptSection SectionString OptGC
|
||||
|
||||
%type <UIntVal> OptAlign OptCAlign
|
||||
|
||||
@ -1090,7 +1090,7 @@ Module *llvm::RunVMAsmParser(llvm::MemoryBuffer *MB) {
|
||||
|
||||
// Function Attributes
|
||||
%token SIGNEXT ZEROEXT NORETURN INREG SRET NOUNWIND NOALIAS BYVAL NEST
|
||||
%token READNONE READONLY
|
||||
%token READNONE READONLY GC
|
||||
|
||||
// Visibility Styles
|
||||
%token DEFAULT HIDDEN PROTECTED
|
||||
@ -1244,6 +1244,12 @@ OptFuncAttrs : /* empty */ { $$ = ParamAttr::None; }
|
||||
}
|
||||
;
|
||||
|
||||
OptGC : /* empty */ { $$ = 0; }
|
||||
| GC STRINGCONSTANT {
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
// OptAlign/OptCAlign - An optional alignment, and an optional alignment with
|
||||
// a comma before it.
|
||||
OptAlign : /*empty*/ { $$ = 0; } |
|
||||
@ -2225,7 +2231,7 @@ ArgList : ArgListH {
|
||||
};
|
||||
|
||||
FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
|
||||
OptFuncAttrs OptSection OptAlign {
|
||||
OptFuncAttrs OptSection OptAlign OptGC {
|
||||
std::string FunctionName(*$3);
|
||||
delete $3; // Free strdup'd memory!
|
||||
|
||||
@ -2328,6 +2334,10 @@ FunctionHeaderH : OptCallingConv ResultTypes GlobalName '(' ArgList ')'
|
||||
Fn->setSection(*$8);
|
||||
delete $8;
|
||||
}
|
||||
if ($10) {
|
||||
Fn->setCollector($10->c_str());
|
||||
delete $10;
|
||||
}
|
||||
|
||||
// Add all of the arguments we parsed to the function...
|
||||
if ($5) { // Is null if empty...
|
||||
|
@ -849,6 +849,7 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
|
||||
|
||||
SmallVector<uint64_t, 64> Record;
|
||||
std::vector<std::string> SectionTable;
|
||||
std::vector<std::string> CollectorTable;
|
||||
|
||||
// Read all the records for this module.
|
||||
while (!Stream.AtEndOfStream()) {
|
||||
@ -974,6 +975,13 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
|
||||
SectionTable.push_back(S);
|
||||
break;
|
||||
}
|
||||
case bitc::MODULE_CODE_COLLECTORNAME: { // SECTIONNAME: [strchr x N]
|
||||
std::string S;
|
||||
if (ConvertToString(Record, 0, S))
|
||||
return Error("Invalid MODULE_CODE_COLLECTORNAME record");
|
||||
CollectorTable.push_back(S);
|
||||
break;
|
||||
}
|
||||
// GLOBALVAR: [type, isconst, initid,
|
||||
// linkage, alignment, section, visibility, threadlocal]
|
||||
case bitc::MODULE_CODE_GLOBALVAR: {
|
||||
@ -1016,7 +1024,7 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
|
||||
break;
|
||||
}
|
||||
// FUNCTION: [type, callingconv, isproto, linkage, paramattr,
|
||||
// alignment, section, visibility]
|
||||
// alignment, section, visibility, collector]
|
||||
case bitc::MODULE_CODE_FUNCTION: {
|
||||
if (Record.size() < 8)
|
||||
return Error("Invalid MODULE_CODE_FUNCTION record");
|
||||
@ -1044,6 +1052,11 @@ bool BitcodeReader::ParseModule(const std::string &ModuleID) {
|
||||
Func->setSection(SectionTable[Record[6]-1]);
|
||||
}
|
||||
Func->setVisibility(GetDecodedVisibility(Record[7]));
|
||||
if (Record.size() > 8 && Record[8]) {
|
||||
if (Record[8]-1 > CollectorTable.size())
|
||||
return Error("Invalid collector ID");
|
||||
Func->setCollector(CollectorTable[Record[8]-1].c_str());
|
||||
}
|
||||
|
||||
ValueList.push_back(Func);
|
||||
|
||||
|
@ -297,9 +297,10 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
||||
WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(),
|
||||
0/*TODO*/, Stream);
|
||||
|
||||
// Emit information about sections, computing how many there are. Also
|
||||
// compute the maximum alignment value.
|
||||
// Emit information about sections and collectors, computing how many there
|
||||
// are. Also compute the maximum alignment value.
|
||||
std::map<std::string, unsigned> SectionMap;
|
||||
std::map<std::string, unsigned> CollectorMap;
|
||||
unsigned MaxAlignment = 0;
|
||||
unsigned MaxGlobalType = 0;
|
||||
for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end();
|
||||
@ -317,13 +318,24 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
||||
}
|
||||
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
|
||||
MaxAlignment = std::max(MaxAlignment, F->getAlignment());
|
||||
if (!F->hasSection()) continue;
|
||||
// Give section names unique ID's.
|
||||
unsigned &Entry = SectionMap[F->getSection()];
|
||||
if (Entry != 0) continue;
|
||||
WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(),
|
||||
0/*TODO*/, Stream);
|
||||
Entry = SectionMap.size();
|
||||
if (F->hasSection()) {
|
||||
// Give section names unique ID's.
|
||||
unsigned &Entry = SectionMap[F->getSection()];
|
||||
if (!Entry) {
|
||||
WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(),
|
||||
0/*TODO*/, Stream);
|
||||
Entry = SectionMap.size();
|
||||
}
|
||||
}
|
||||
if (F->hasCollector()) {
|
||||
// Same for collector names.
|
||||
unsigned &Entry = CollectorMap[F->getCollector()];
|
||||
if (!Entry) {
|
||||
WriteStringRecord(bitc::MODULE_CODE_COLLECTORNAME, F->getCollector(),
|
||||
0/*TODO*/, Stream);
|
||||
Entry = CollectorMap.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emit abbrev for globals, now that we know # sections and max alignment.
|
||||
@ -383,7 +395,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
||||
// Emit the function proto information.
|
||||
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
|
||||
// FUNCTION: [type, callingconv, isproto, paramattr,
|
||||
// linkage, alignment, section, visibility]
|
||||
// linkage, alignment, section, visibility, collector]
|
||||
Vals.push_back(VE.getTypeID(F->getType()));
|
||||
Vals.push_back(F->getCallingConv());
|
||||
Vals.push_back(F->isDeclaration());
|
||||
@ -392,6 +404,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
||||
Vals.push_back(Log2_32(F->getAlignment())+1);
|
||||
Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0);
|
||||
Vals.push_back(getEncodedVisibility(F));
|
||||
Vals.push_back(F->hasCollector() ? CollectorMap[F->getCollector()] : 0);
|
||||
|
||||
unsigned AbbrevToUse = 0;
|
||||
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
|
||||
|
@ -67,6 +67,8 @@ Module *llvm::CloneModule(const Module *M,
|
||||
GlobalValue::ExternalLinkage, I->getName(), New);
|
||||
NF->setCallingConv(I->getCallingConv());
|
||||
NF->setParamAttrs(I->getParamAttrs());
|
||||
if (I->hasCollector())
|
||||
NF->setCollector(I->getCollector());
|
||||
ValueMap[I]= NF;
|
||||
}
|
||||
|
||||
|
@ -1112,6 +1112,8 @@ void AssemblyWriter::printFunction(const Function *F) {
|
||||
Out << " section \"" << F->getSection() << '"';
|
||||
if (F->getAlignment())
|
||||
Out << " align " << F->getAlignment();
|
||||
if (F->hasCollector())
|
||||
Out << " gc \"" << F->getCollector() << '"';
|
||||
|
||||
if (F->isDeclaration()) {
|
||||
Out << "\n";
|
||||
|
@ -619,6 +619,19 @@ void LLVMSetFunctionCallConv(LLVMValueRef Fn, unsigned CC) {
|
||||
return unwrap<Function>(Fn)->setCallingConv(CC);
|
||||
}
|
||||
|
||||
const char *LLVMGetCollector(LLVMValueRef Fn) {
|
||||
Function *F = unwrap<Function>(Fn);
|
||||
return F->hasCollector()? F->getCollector() : 0;
|
||||
}
|
||||
|
||||
void LLVMSetCollector(LLVMValueRef Fn, const char *Coll) {
|
||||
Function *F = unwrap<Function>(Fn);
|
||||
if (Coll)
|
||||
F->setCollector(Coll);
|
||||
else
|
||||
F->clearCollector();
|
||||
}
|
||||
|
||||
/*--.. Operations on basic blocks ..........................................--*/
|
||||
|
||||
LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef Bb) {
|
||||
|
@ -17,8 +17,10 @@
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/Support/LeakDetector.h"
|
||||
#include "llvm/Support/ManagedStatic.h"
|
||||
#include "llvm/Support/StringPool.h"
|
||||
#include "SymbolTableListTraitsImpl.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
using namespace llvm;
|
||||
|
||||
@ -297,6 +299,9 @@ Function::~Function() {
|
||||
// Drop our reference to the parameter attributes, if any.
|
||||
if (ParamAttrs)
|
||||
ParamAttrs->dropRef();
|
||||
|
||||
// Remove the function from the on-the-side collector table.
|
||||
clearCollector();
|
||||
}
|
||||
|
||||
void Function::BuildLazyArguments() const {
|
||||
@ -379,6 +384,40 @@ void Function::dropAllReferences() {
|
||||
BasicBlocks.clear(); // Delete all basic blocks...
|
||||
}
|
||||
|
||||
// Maintain the collector name for each function in an on-the-side table. This
|
||||
// saves allocating an additional word in Function for programs which do not use
|
||||
// GC (i.e., most programs) at the cost of increased overhead for clients which
|
||||
// do use GC.
|
||||
static DenseMap<const Function*,PooledStringPtr> *CollectorNames;
|
||||
static StringPool *CollectorNamePool;
|
||||
|
||||
bool Function::hasCollector() const {
|
||||
return CollectorNames && CollectorNames->count(this);
|
||||
}
|
||||
|
||||
const char *Function::getCollector() const {
|
||||
assert(hasCollector() && "Function has no collector");
|
||||
return *(*CollectorNames)[this];
|
||||
}
|
||||
|
||||
void Function::setCollector(const char *Str) {
|
||||
if (!CollectorNamePool)
|
||||
CollectorNamePool = new StringPool();
|
||||
if (!CollectorNames)
|
||||
CollectorNames = new DenseMap<const Function*,PooledStringPtr>();
|
||||
(*CollectorNames)[this] = CollectorNamePool->intern(Str);
|
||||
}
|
||||
|
||||
void Function::clearCollector() {
|
||||
if (CollectorNames) {
|
||||
CollectorNames->erase(this);
|
||||
if (CollectorNames->empty()) {
|
||||
delete CollectorNames;
|
||||
CollectorNames = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// getIntrinsicID - This method returns the ID number of the specified
|
||||
/// function, or Intrinsic::not_intrinsic if the function is not an
|
||||
/// intrinsic, or if the pointer is null. This value is always defined to be
|
||||
|
12
test/Assembler/2007-09-29-GC.ll
Normal file
12
test/Assembler/2007-09-29-GC.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: llvm-as < %s | llvm-dis | grep {@f.*gc.*shadowstack}
|
||||
; RUN: llvm-as < %s | llvm-dis | grep {@g.*gc.*java}
|
||||
|
||||
define void @f() gc "shadowstack" {
|
||||
entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @g() gc "java" {
|
||||
entry:
|
||||
ret void
|
||||
}
|
@ -25,7 +25,8 @@ let insist cond =
|
||||
exit_status := 10;
|
||||
" FAIL "
|
||||
end in
|
||||
prerr_endline (msg ^ (string_of_int !case_num))
|
||||
prerr_endline (" " ^ (string_of_int !case_num) ^ if cond then ""
|
||||
else " FAIL")
|
||||
|
||||
let suite name f =
|
||||
prerr_endline (name ^ ":");
|
||||
@ -490,7 +491,20 @@ let test_functions () =
|
||||
insist (ccc = function_call_conv fn);
|
||||
set_function_call_conv fastcc fn;
|
||||
insist (fastcc = function_call_conv fn);
|
||||
ignore (build_unreachable (builder_at_end (entry_block fn)))
|
||||
ignore (build_unreachable (builder_at_end (entry_block fn)));
|
||||
|
||||
begin group "collector";
|
||||
(* RUN: grep {Fn6.*gc.*shadowstack} < %t.ll
|
||||
*)
|
||||
let fn = define_function "Fn6" ty m in
|
||||
insist (None = collector fn);
|
||||
set_collector (Some "ocaml") fn;
|
||||
insist (Some "ocaml" = collector fn);
|
||||
set_collector None fn;
|
||||
insist (None = collector fn);
|
||||
set_collector (Some "shadowstack") fn;
|
||||
ignore (build_unreachable (builder_at_end (entry_block fn)));
|
||||
end
|
||||
|
||||
|
||||
(*===-- Basic Blocks ------------------------------------------------------===*)
|
||||
@ -749,7 +763,6 @@ let test_builder () =
|
||||
let t3 = const_vector [| one; one; zero; zero |] in
|
||||
let vec1 = build_insertelement t1 p1 p2 "Vec1" atentry in
|
||||
let vec2 = build_insertelement t2 p1 p2 "Vec2" atentry in
|
||||
let vec3 = build_insertelement t3 p1 p2 "Vec3" atentry in
|
||||
|
||||
ignore (build_extractelement vec1 p2 "Inst49" atentry);
|
||||
ignore (build_insertelement vec1 p1 p2 "Inst50" atentry);
|
||||
|
@ -7,7 +7,7 @@ declare void @llvm_gc_initialize(i32)
|
||||
declare void @llvm.gcroot(i8**, i8*)
|
||||
declare void @llvm.gcwrite(i8*, i8*, i8**)
|
||||
|
||||
define i32 @main() {
|
||||
define i32 @main() gc "shadow-stack" {
|
||||
entry:
|
||||
%A = alloca i8*
|
||||
%B = alloca i8**
|
||||
|
Loading…
Reference in New Issue
Block a user